本文共 1733 字,大约阅读时间需要 5 分钟。
旧的没有搬过来,先写一下新的感悟。
ECMAScript中,闭包指的是:从理论角度:所有的函数。因为它们都在创建的时候就将上层上下文的数据保存起来了。哪怕是简单的全局变量也是如此,因为函数中访问全局变量就相当于是在访问自由变量,这个时候使用最外层的作用域。从实践角度:以下函数才算是闭包: 1.即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回) 2.在代码中引用了自由变量
什么是自由变量:
自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量。
那么我们现在只考虑实践角度,第二点很好满足,第一点有一丢丢难呢。
先看下闭包:
function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f;}var foo = checkscope();foo();
按照我的上一篇js的上下文。
理论上scope 是访问不到var scope = "local scope";的。
我在这里简单的分析一下,详细可以去看我的。
首先得到全局上下文,进入栈中。
然后checkscope 上下文进入栈。
当执行完毕,checkscope 上下文出栈了。
问题就在这里,既然上下文出栈了,那么应该f这个函数执行的时候,就应该访问不到checkscope 的上下文了,垃圾就会回收checkscope 的上下文。
这个问题就出现了。
但是你没有有听说过闭包造成内存问题?
问题就出再f创建的时候,会扫码他所在环境的上下文,如果引用了上下文的作用链对象,那么会保留上下文。
function a(){ var x=1; var c= function b() { return function (){ return x; } } return function() { return c; }}
console.log(a()()()());
只要是作用链上的都会保留到,返回结果为1。var data = [];for (var i = 0; i < 3; i++) { data[i] = function () { console.log(i); };}data[0]();data[1]();data[2]();
为何其会返回都是3?
按照上下文理解,那么是:在执行匿名函数的时候,上下文栈中只剩下全局上下文,访问的就只有去全局的。
那么可以这样写:
var data = [];for (var i = 0; i < 3; i++) { data[i] = (function (i) { return function(){ console.log(i); } })(i);}data[0]();data[1]();data[2]();
关键部分在这个i:
(function (i) { return function(){ console.log(i); } })(i);
这样i,相当于这样的。
(function (i) { var i=i; return function(){ console.log(i); } })(i);
这就是说这个i和循环中的i没有半毛钱关系,因为其不是引用对象。
下面我写了一个引用对象的:
var data=[];var args={i:0};for (var i = 0; i < 3; i++) { args.i=i; data[i] = (function (args) { return function () { console.log(args.i); } })(args);}data[0]();data[1]();data[2]();
这样的闭包不仅没有效果,而且还出内存问题。
转载地址:http://dnskz.baihongyu.com/