We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
闭包属于一种特殊的作用域,称为静态作用域。它的定义可以理解为: 父函数被销毁 的情况下,返回出的子函数的[[scope]]中仍然保留着父级的单变量对象和作用域链,因此可以继续访问到父级的变量对象,这样的函数称为闭包。
[[scope]]
优点:
缺点:
function test1(){ function test2(){ var b = 2; console.log(a); } var a = 1; return test2; } var c = 3; var test3 = test1(); test3();
上面代码是一个闭包,下面将对原型链过程详细描述
function test1(){ } var c = 3; var test3 = test1();
当test1函数被定义时,系统生成[[scope]]属性,[[scope]]保存该函数的作用域链,该作用域链的第0位存储当前环境下的全局执行期上下文GO,GO里存储全局下的所有对象,其中包含函数test1和全局变量c
function test1(){ function test2(){ } var a = 1; return test2; } var c = 3; var test3 = test1();
当test1函数被执行时(前一刻),函数test2被定义
当test1函数被执行结束时,因为test2被返回到外部,且被全局变量test3接受。这时test1的AO并没有销毁,只是把线剪断了,test2的作用域链还是连着的
AO
作用域链
test3执行时,test2的作用域链增加自己的AO,当打印a的时候,在自己的AO上没有查找到,则向test1的AO查找。再次执行test3时,实际操作的仍然是原来test1的AO
当test3执行结束后,test2的AO被销毁,但原来test1的AO仍然存在且被test2连着
示例1
function fun(n, o) { console.log(o); return { fun: function(m) { return fun(m, n); } } } var a = fun(0); a.fun(1); // undefined // 0
示例2
function fun(n, o) { console.log(o); return { fun: function(m) { return fun(m, n); } } } var a = fun(0); a.fun(1); a.fun(2); a.fun(3); // undefined // 0 // 0 // 0
示例3
function fun(n, o) { console.log(o); return { fun: function(m) { return fun(m, n); } } } var a = fun(0) // undefined .fun(1) // 0 .fun(2) // 1 .fun(3); // 2
首先JavaScript具有自动垃圾回收机制,会找出不再使用的变量,然后释放其占用的内存。常用的方法有两种,即标记清除和引用计数
语言引擎有一张引用表,保存了内存里面所有的资源(各种值)的引用次数。如果一个值的引用次数为0,就表示这个值不再用到了,因此就可以将这块内存释放。但是引用计数有个最大的问题: 循环引用。
function func() { let obj1 = {}; let obj2 = {}; obj1.a = obj2; // obj1 引用 obj2 obj2.a = obj1; // obj2 引用 obj1 }
当函数func执行结束后,返回值为undefined,所以整个函数以及内部的变量都应该被回收,但根据引用计数方法,obj1和 obj2的引用次数都不为0,所以他们不会被回收。
func
undefined
obj1
obj2
0
要解决循环引用的问题,最好是在不使用它们的时候手工将它们设为空。上面的例子可以这么做:
obj1 = null; obj2 = null;
JavaScript 中有个全局对象,浏览器中是window。定期的,垃圾回收期将从这个全局对象开始,找所有从这个全局对象开始引用的对象,再找这些对象引用的对象...对这些活着的对象进行标记,这是标记阶段。清除阶段就是清除那些没有被标记的对象。
window
The text was updated successfully, but these errors were encountered:
No branches or pull requests
什么是闭包
闭包属于一种特殊的作用域,称为静态作用域。它的定义可以理解为: 父函数被销毁 的情况下,返回出的子函数的
[[scope]]
中仍然保留着父级的单变量对象和作用域链,因此可以继续访问到父级的变量对象,这样的函数称为闭包。闭包优缺点
优点:
缺点:
闭包过程详解
上面代码是一个闭包,下面将对原型链过程详细描述
一、当test1函数被定义时
当test1函数被定义时,系统生成[[scope]]属性,[[scope]]保存该函数的作用域链,该作用域链的第0位存储当前环境下的全局执行期上下文GO,GO里存储全局下的所有对象,其中包含函数test1和全局变量c
二、当test1函数被执行时(前一刻)
当test1函数被执行时(前一刻),函数test2被定义
三、当test1函数被执行结束时
当test1函数被执行结束时,因为test2被返回到外部,且被全局变量test3接受。这时test1的
AO
并没有销毁,只是把线剪断了,test2的作用域链
还是连着的四、test3执行时
test3执行时,test2的作用域链增加自己的AO,当打印a的时候,在自己的AO上没有查找到,则向test1的AO查找。再次执行test3时,实际操作的仍然是原来test1的AO
五、test3执行结束后
当test3执行结束后,test2的AO被销毁,但原来test1的AO仍然存在且被test2连着
示例
垃圾回收机制
首先JavaScript具有自动垃圾回收机制,会找出不再使用的变量,然后释放其占用的内存。常用的方法有两种,即标记清除和引用计数
引用计数
语言引擎有一张引用表,保存了内存里面所有的资源(各种值)的引用次数。如果一个值的引用次数为0,就表示这个值不再用到了,因此就可以将这块内存释放。但是引用计数有个最大的问题: 循环引用。
当函数
func
执行结束后,返回值为undefined
,所以整个函数以及内部的变量都应该被回收,但根据引用计数方法,obj1
和obj2
的引用次数都不为0
,所以他们不会被回收。要解决循环引用的问题,最好是在不使用它们的时候手工将它们设为空。上面的例子可以这么做:
标记清除
JavaScript 中有个全局对象,浏览器中是
window
。定期的,垃圾回收期将从这个全局对象开始,找所有从这个全局对象开始引用的对象,再找这些对象引用的对象...对这些活着的对象进行标记,这是标记阶段。清除阶段就是清除那些没有被标记的对象。参考文献
The text was updated successfully, but these errors were encountered: