定义函数的方式:①函数声明 ②函数表达式
①函数声明
重要特征:函数声明提升:在执行代码之前会先读取函数声明。
②函数表达式
函数表达式在使用前必须先赋值。
把函数当成值来使用时,都可以使用匿名函数。
7.1 递归
递归函数:一个函数通过名字调用自身。
问题:如果在通过名字调用函数前,函数被修改了,会导致问题。
解决:①arguments.callee一个指向正在执行的函数的指针。(严格模式下出错)
②命名函数表达式
|
|
7.2 闭包
闭包函数:有权访问另一个函数作用域的变量的函数。
创建方式:在一个函数内部创建另一个函数。
每个执行环境都有一个表示变量的对象。
全局环境的变量对象始终存在,局部变量对象只在执行过程中存在。
作用域链本质:一个指向变量对象的指针列表,它只引用不包含变量对象。
一般来说:当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域。但闭包不同。
闭包函数:闭包函数会将包含函数的活动对象添加到它的作用域链中。
7.2.1 闭包与变量
闭包只能取得包含函数中任何变量的最后一个值。
闭包所保存的是整个变量对象,而不是某个变量。
7.2.2 关于this对象
this对象:在运行时基于函数的执行环境绑定的。全局函数中:this = window;函数被当做某个对象的方法调用:this = 某个对象;匿名函数:this=window;通过call()/apply():this指向对象。
目的:在闭包函数中(通常是匿名函数)使用this,希望this返回的是外部函数对象。
方法:把外部作用域中的this对象保存在一个闭包能访问到的变量里。
|
|
7.2.3 内存泄漏
如果闭包的作用域链中保存着一个HTML元素,意味着该元素将无法被销毁。
7.3 模仿块级作用域
js没有块级作用域:在块语句中定义的变量,实际上是在包含函数中而非语句中创建的。
重复声明:js会忽略后续声明,但会执行后续声明中的变量初始化。
私有作用域:用作块级作用域的匿名函数
(function(){
// 这里是块级作用域
})();
定义并立即调用一个匿名函数。将函数声明包含在一对圆括号中,表示它实际上是一个函数表达式。而之后的另一对圆括号会立即调用这个函数。
在匿名函数中定义的任何变量,都会在执行结束时被销毁。
用法:用在全局作用域中的函数外部,从而限制向全局作用域中添加过多的变量和函数。
7.4 私有变量
js中没有私有成员的概念,所有对象属性都是公有的。但是有一个私有变量的概念。
私有变量:任何在函数中定义的局部变量、函数的参数和函数内部定义的其他函数。
特权方法:
把有权访问私有变量和私有函数的公有方法称为特权方法。
创建特权方式的方法①:
在构造函数中定义特权方法
|
|
缺点就是使用构造函数的通病:每个实例都会创建同样一组新方法。
7.4.1 静态私有变量
创建特权方式的方法②:
|
|
缺点:每个实例都没有自己的私有变量。
7.4.2 模块模式
7.4.3 增强的模块模式