JavaScript:词汇封闭还是其他什么?

时间:2010-10-26 04:03:08

标签: javascript

考虑这个脚本:

function Obj(prop) {
    this.prop = prop;
}

var NS = {
    strings: ['first','second','third'],
    objs: [],
    f1: function() {
        for (s in this.strings) {
            var obj = new Obj(this.strings[s]);
            obj.f2 = function() {
                alert(obj.prop);
            }
            this.objs.push(obj);
        }
    }
}

NS.f1();
NS.objs[0].f2(); // third
NS.objs[1].f2(); // third
NS.objs[2].f2(); // third

不完全是预期的输出,但是当我更新到这个时:

function Obj(prop) {
    this.prop = prop;
}

var NS = {
    strings: ['first','second','third'],
    objs: [],
    f1: function() {
        for (s in this.strings) {
            var obj = new Obj(this.strings[s]);
            this.wire(obj); // replaces previous function def
            this.objs.push(obj);
        }
    },
    wire: function(obj) {
        obj.f2 = function() {
            alert(obj.prop);
        } // exact same code and function def as the first example
    }
}

NS.f1();
NS.objs[0].f2(); // first
NS.objs[1].f2(); // second
NS.objs[2].f2(); // third

这似乎有效,我不知道为什么。任何人都可以开导我吗?感谢

2 个答案:

答案 0 :(得分:2)

查看http://jibbering.com/faq/notes/closures/

它将解释“其他内容”以及您可能想知道的JavaScript变量和范围如何工作的所有内容。 JavaScript使用“执行上下文”闭包,而不是“词法变量”闭包(编辑:它仍然是一个词法绑定,只是不一定如预期 - 见下文)。

在第一个示例中,相同的 obj被绑定了三次,或者更确切地说,相同的obj属性(编辑:规范不需要这个,但是调用单一绑定执行上下文是共享的一种属性解释方法!

var没有“声明”变量(编辑:它是一个适用于整个范围的注释,不受{}的影响,除了以下内容之外)function是如何一个人可以引入新的范围 - >新的执行上下文(这就是第二个示例按预期工作的原因)。 function(或eval /类似)引入了新的范围

快乐的编码。

答案 1 :(得分:1)

F1

...在单个闭包中只有一个obj,分配3次

F2

...最终在三个闭包中加上3个obj(加上f1也有一个闭包),每个闭包一次

关于JS的一个有趣的事情可能有所帮助:以下两个函数做同样的事情:

function a1() {
  var a,b,c;

  a = 1;
  b = 2;
  c = 3;
}

function a2() {
  a = 1;
  b = 2;
  c = 3;

  var a,b,c;
}

var声明始终在函数级范围内运行,无论函数在何处或嵌套在内部块中有多深。