结合上篇所说的 JS 函数的这些符号定义,再拓展说下JS 的闭包
参考网文
全面理解Javascript闭包和闭包的几种写法及用途 Javascript闭包——懂不懂由你,反正我是懂了 彻底搞懂JS闭包各种坑 javascript深入理解js闭包 — 大神制作 ES5中的函数 阮一峰关于 Javascript 中闭包的解读是否正确?
感觉对于闭包的学习,无法光看一两篇文章就能明白,需要多看几篇才能有些许的理解
知识点: 1.保护函数内的变量安全: 在ECMAScript 6之前,JS中是没有局部作用域的,所以一般使用闭包来模拟局部作用域,以使得里面的写的代码不跟外面的冲突。 e.g. ( function ( ) { })( );
知识拓展说明
①( function ( $ ) { // $ 加这个参数用于接受jQuery对象,这样一来就可以在内部代码中使用$
...
})( jQuery); // 传递jQuery对象
当然,同理可用第二括号所表示的匿名函数来传参
( function ( param ) { // param 便是 第二个参数所传的data值
...
})( data ); // 传外部的参数数值data
②若内部function调用其他函数命名写为 this._unoredered( ),中间加 _ 是为表明该方法 unoredered( ) 仅在内部使用,而不提供外部调用
( function ( $ ) {
...
this._unoredered( )
...
PreLoad.prototype._unoredered = function ( ) { } // 将该面向的对象的方法写在原型上,可使其在每次实例化时都保持只有一份
})( jQuery);
2.何为闭包? ① 官方是:“闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。” ② 概念来说:闭包是能够访问另一个函数作用域的变量的函数。即闭包就是一个函数,这个函数能够访问其他函数的作用域中的变量,而这些变量,便可理解是该作用域下的全局变量。
所以, 通俗来说,js中所有function( )内都可以去访问全局变量,即 JavaScript中所有的function都是一个闭包。不过一般来说,嵌套的function所产生的闭包更为强大,也是大部分时候我们所谓的“闭包”。
3.链式作用域: Javascript语言特有的“链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。 即 可以 子对象 访问 父对象内的变量,但父对象 不能访问到 子对象内的变量。
4.闭包的用途: ①通过内嵌func 可以读取函数内部的变量 由于function( ) {} 存在函数内的局部作用域,所有func内定义的变量属于内部变量,外部函数是无法访问到内部变量的 ②可让闭包函数外部的变量的值始终保持在内存中,只要允许的function为闭包,那所运行的外部变量就会被保存在内存中。
e.g.
function f1() {
var n = 999;
nAdd = function() {
n += 1
}
function f2() {
alert(n)
}
return f2
}
var result = f1();
result();
nAdd();
result();
在上面代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制GC(garbage collection)回收。
这段代码中另一个值得注意的地方,就是“nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。
5.如果可以理解下面代码的运行结果,基本就算理解闭包的运行机制:
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
return function() {
return this.name
}
}
};
个人理解:
① 多次单独运行 alert(object.getNameFunc()()); 均是返回 The Window. 说明运行一遍后,The Window已被存至内存,并且方法object.getNameFunc()也并没有被清除回收
② 通过打log,getNameFunc内部this指的是object ,但getNameFunc的return function() 闭包里的this 指的是window,估计闭包 根据作用域链找到上一级变量为 window的缘故。
③ 代码类似上图,可能是在位置A所处的作用域链没有找到name,所以就指向window,但该作用域链还待研究?
闭包在执行的时候,会使用arguments和其他的命名参数创建自己的活动对象,闭包的作用域链中会包含外部函数的活动对象,当在函数中访问一个变量时,就会从其作用域链中搜索直到找到为止.所以这就是闭包为什么可以访问其外部函数的变量.
补充:$(function(){ })
- $选择符,jquery自己的定义,$(function(){ })是定义一个匿名函数
- $(document).ready(function(){});的简写