一、函数声明和函数表达式

定义函数有两种方式:函数声明和函数表达式。它们之间一个重要的区别是函数提升。

1.函数声明会进行函数提升,所以函数调用在函数声明之前也不会报错:

test();
function test(){
alert(1);
}

2.函数表达式不会进行函数提升,函数调用在函数声明之前的话会报错:

test(); // test is not a function
var test=function(){
alert(1);
}

二、递归函数

递归函数是通过在函数内部调用自身实现的。

①直接使用函数名进行递归调用

function f(num){
if(num==1){
return 1;
}else{
return num*f(num-1);
}
}
console.log(f(4));//
console.log(f(5));//

这种实现的缺点是,在函数内部直接写死了函数名称。如果进行如下设置就会报错:

var test=f;
f=null;
console.log(test(3));//报错, f is not a function

②通过arguments.callee解决,arguments.callee是一个指向正在执行的函数的指针。这样就避免了上述问题。

function f(num){
if(num==1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
console.log(f(4));//
console.log(f(5));//
var test=f;
f=null;
console.log(test(3));//

不过这种方式还有一个缺点,就是在严格模式下会执行失败。

添加"use strict"后执行会报错:

'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

③采用命名函数表达式可以在严格模式下成功。

"use strict";
var f=function t(num){
if(num==1){
return 1;
}else{
return num*t(num-1);
}
}
console.log(f(4));//
console.log(f(5));//
var test=f;
f=null;
console.log(test(3));//

三、闭包

闭包是有权访问另一个函数作用域内变量的函数。创建闭包的常见方式就是在一个函数内创建另外一个函数。在另一个函数内部定义的函数,会把外部函数的作用域添加到其作用域链中。

1.闭包与变量

①闭包只能取得包含函数中任意变量的最后一个值。例如:

function createFunctions(){
var result=new Array();
for(var i=0;i<10;i++){
result[i]=function(){
return i;
}
}
return result;
}
var result=createFunctions();
result[1]();//

这个方法调用传入1-10返回结果都是10,这并不符合预期。

②通过匿名函数进行改造:

function createFunctions(){
var result=new Array();
for(var i=0;i<10;i++){
result[i]=(function(num){
return num;
})(i);
}
return result;
}
var result=createFunctions();
result[2];//

改造后的运行结果符合我们的预期了。因为将i传递给num命名参数时是按值传递的。

2.闭包中的this

this变量是在运行时基于函数的执行环境绑定的。

在全局执行环境中,this指向window对象;

当函数作为某个对象的方法时,this等于那个对象;

匿名函数的执行具有全局性,this通常指向window对象。

①闭包中this实例:

var name='window';
var object={
name:"object",
getName:function(){
return function(){
return this.name;
}
}
};
object.getName()();//window

②先将闭包外部作用域中的this保存到一个闭包能访问到的变量中,这样就可以让闭包访问相应的对象了。例如:

var name='window';
var object={
name:"object",
getName:function(){
var that=this;
return function(){
return that.name;
}
}
};
object.getName()();//object

读javascript高级程序设计03-函数表达式、闭包、私有变量的更多相关文章

  1. 读javascript高级程序设计00-目录

    javascript高级编程读书笔记系列,也是本砖头书.感觉js是一种很好上手的语言,不过本书细细读来发现了很多之前不了解的细节,受益良多.<br/>本笔记是为了方便日后查阅,仅作学习交流 ...

  2. 读javascript高级程序设计-目录

    javascript高级编程读书笔记系列,也是本砖头书.感觉js是一种很好上手的语言,不过本书细细读来发现了很多之前不了解的细节,受益良多.<br/>本笔记是为了方便日后查阅,仅作学习交流 ...

  3. 读javascript高级程序设计08-引用类型之Global、Math、String

    一.Global 所有在全局作用域定义的属性和方法,都属于Global对象. 1.URI编码: encodeURI():主要用于对整个URI编码.它不会对本身属于URI的特殊字符进行编码. encod ...

  4. 前端(十三)—— JavaScript高级:回调函数、闭包、循环绑定、面向对象、定时器

    回调函数.闭包.循环绑定.面向对象.定时器 一.函数高级 1.函数回调 // 回调函数 function callback(data) {} // 逻辑函数 function func(callbac ...

  5. 读javascript高级程序设计02-变量作用域

    一. 延长作用域链 有些语句可以在作用域前端临时增加一个变量对象,该变量对象在代码执行完成后会被移除. ①with语句延长作用域. function buildUrl(){ var qs=" ...

  6. JavaScript高级程序设计学习笔记第四章--变量、作用域和内存问题

    1.变量可能包含两种不同数据类型的值:基本类型值和引用类型值. 基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象. 2.变量复制 如果从一个变量向另一个变量复制基本类型的值,会在 ...

  7. 读javascript高级程序设计01-基本概念、数据类型、函数

    一. javascript构成 1.javascript实现由三部分组成: ECMAScript:核心语言功能 DOM:文档对象模型,提供访问和操作网页内容的方法和接口 BOM:浏览器对象模型,提供与 ...

  8. 读javascript高级程序设计16-几条函数小技巧

    内容概要 作用域安全的构造函数 惰性载入函数 函数绑定 函数节流 一.作用域安全的构造函数 我们知道,当使用new操作符调用构造函数时,构造函数内部的this会指向新创建对象的实例. function ...

  9. 读javascript高级程序设计10-DOM

    一.节点关系 元素的childNodes属性来表示其所有子节点,它是一个NodeList对象,会随着DOM结构的变化动态变化. hasChildNodes():是否有子节点. var headline ...

随机推荐

  1. 匈牙利命名法、骆驼命名法、帕斯卡(pascal)命名法

    (2008-05-24 13:37:55) 转载▼ 标签: 杂谈 分类: 编程杂文 一.匈牙利命名法:         广泛应用于象Microsoft Windows这样的环境中. Windows 编 ...

  2. 闭包(closure)

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascript初学者应该是很有用的. 一.变量的作用域 要理解 ...

  3. HTML5中的时间类型,另外EL表达式的时间值来读取时间,并且还可以更改时间

    HTML5规范里只规定date新型input输入类型,并没有规定日历弹出框的实现和样式.所以,各浏览器根据自己的设计实现日历.目前只有谷歌浏览器完全实现日历功能.相信这种局面很快就会结束,所有的浏览器 ...

  4. paper 112:hellinger distance

    在概率论和统计理论中,Hellinger距离被用来度量两个概率分布的相似度.它是f散度的一种(f散度——度量两个概率分布相似度的指标).Hellinger距离被定义成Hellinger积分的形式,这种 ...

  5. 安卓开发经验分享:资源、UI、函数库、测试、构建一个都不能少(转)

    除了高超的武艺,每位黑忍者还需要装备最好的武器.在软件开发的世界里,好的工具能让我们的生活变得更轻松,在更短的时间里写出更棒的代码. 时光回到2008年,那时安卓还很年轻.只有几个相关的博客和谷歌官方 ...

  6. Delegate(委托与事件)

    Delegate可以当它是一个占位符,比如你在写代码的时候并不知道你将要处理的是什么.你只需要知道你将要引入的参数类型和输出类型是什么并定义它即可.这就是书本上所传达的方法签名必须相同的意思. 系统自 ...

  7. OBD K线抓包 II

    9141的激活过程是先发WakeUp, 然后用Link: const u8 LinkCmd9141[7]  = {6,0x68,0x6A,0xF1,0x01,0x00,0xC4}; 14230的Lin ...

  8. opensuse-13.1体验

    1  livecd安装 下载地址 http://software.opensuse.org/131/zh_CN 我下载的kde版本的livecd,不像ubuntu支持ultraiso的U盘安装,也不支 ...

  9. html5 Web Storage(localStorage(),sessionStorage())

    Web Storage包括了两种存储方式:sessionStorage和localStorage sessionStorage 是会话级别的存储,这些数据只有在同一个会话中的页面才能访问并且当会话结束 ...

  10. calico docker 应用实例

    在上一篇文章<quay.io/coreos/etcd 基于Docker镜像的集群搭建>中,介绍了ETCD集群的搭建.在此基础上,我们进一步实践calico docker的应用. PaaS ...