Javascript 的闭包如何工作?

来源:互联网 发布:最简单的小游戏的编程 编辑:程序博客网 时间:2024/05/16 07:16

原文地址:How do javascript closures work?

任何时候当你看到函数关键字中有另外一个函数时,里面的函数都可以方位外部的函数。

function foo(x) {  var tmp = 3;  function bar(y) {    alert(x + y + (++tmp)); // will alert 16  }  bar(10);}foo(2);

结果总是16,因为bar可以方位x,x在foo中被定义为一个参数。
这就是闭包。函数不一定返回,从而叫做闭包。

function foo(x) {  var tmp = 3;  return function (y) {    alert(x + y + (++tmp)); // will also alert 16  }}var bar = foo(2); // bar is now a closure.bar(10);

上面的函数也会返回16,因为bar仍然可以引用xtmp,尽管不直接存在于作用域中。

然而,因为tmp 仍然存在与bar的闭包中。它也会增加。每次你调用bar时,他都会增加。下面是一个关于闭包的简单例子:

var a = 10;var b = 6;function test() {  console.log(a); // will output 10  console.log(b); // will output 6}test();

当Javascript函数被调用时,一个新的执行上下文被创建。连同函数参数和父对象, 这个执行上下文也接受所有的外部声明(在上面的例子中,‘a’和‘b’都是)

有可能创建不止一个闭包函数,或者通过设置它们的全局变量返回它们的列表。这些都有一个相同的x和相同的tmp,他们没有复制自己。

这个数字x是数字字面量。作为在Javascript的其他字面量,当foo被调用时,这个数字x被作为参数复制到了foo

另一方面,Javascript在处理对象时总是使用参考引用。也就是说,你通过对象调用foo,闭包返回最初对象的引用。

function foo(x) {  var tmp = 3;  return function (y) {    alert(x + y + tmp);    x.memb = x.memb ? x.memb + 1 : 1;    alert(x.memb);  }}var age = 2;var bar = foo(age); // bar is now a closure referencing age.bar(10);

正如期望的,每次调用bar(10)都会增加x.memb。没有预料的是,x简单引用同一个对象作为age的变量。通过几次调用bar后,age.memb将会是2! 这参考对HTML对象的内存泄露的基础。

0 0
原创粉丝点击