请教高手,广义而言,所有JS的函数都可以称为闭包,因为JS函数在创建时保存了当前的词法环境这句话怎么理解。
闭包的设计是为了要解决函數自變量問題(Funarg problem),闭包与自由变量的定义如下:
闭包是代码块和创建该代码块的上下文中数据的结合。
自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量。
ECMAScript使用了几项技术的设计,其中之一是作用域链来解决这个问题,在所有的函数中都有一个[[Scope]]物件来保存变量对象,其中也包含了全域对象,按照作用域链与[[Scope]]的设计,函数在最后执行会依包含其中的变量来执行。
因为ECMAScript并没有明确的规范当函数如果不需要引用自由变量时,是否需要把上层的作用域链也保存在[[Scope]]之中,所以在理论上会认为所有的函数都是有同样的设计。
[[Scope]]是一个包含了所有上层变量对象的分层链,它属于当前函数上下文,并在函数创建的时候,保存在函数中。
因此,在理论上认为所有的函数在创建时,就会把上层的作用域键也保存住,即使是最外层的全域也是。所以所有的函数都认为是一个闭包。
但从实践角度:以下函数才算是闭包:
即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回)
在代码中引用了自由变量
以上内容均参考自: http://goddyzhao.tumblr.com/p...与http://goddyzhao.tumblr.com/p...。中文的需要深入自行参考。
因为 ECMA262 中规定 JS 使用作用域链来实现闭包。JS 的顶层函数关联全局域,嵌套函数关联局部域,这个形式是统一的。
另外 JS 不存在一个直接访问的“全局域”。任何全局域的访问都是根据作用域链搜索上去的。这个和某些语言,碧如 C++、Java 很不一样。
// scope0 (global)
var a = 0;
(() => { // function0
// function0.[[scope]] == scope0
// scope1
// scope1.callee == function0
var a = 1;
(() => { // function1
//function1.[[scope]] == scope0
// scope2
// scope2.callee == function1
// scope1.a
console.log(a); // 1
a = 2;
})();
console.log(a); //2
})();
console.log(a); // 0
上面那段代码的function1
,它自己的作用域scope2
中找不到a
,于是到它的[[scope]]
也就是scope1
里面找。
不知道这么说你能不能明白。
10 回答11.2k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
3 回答2.3k 阅读✓ 已解决
3 回答2.1k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
js的执行环境本身就是一个scope(浏览器的window/node的global),我们通常称之为全局作用域。每个函数,不论多深,都可以认为是全局scope的子作用域,可以理解为闭包。