Javascript 是什么导致了这种行为?(闭包及参考资料)

Javascript 是什么导致了这种行为?(闭包及参考资料),javascript,Javascript,我一直在试验通过自调用匿名函数将方法和变量附加到对象的方法,但遇到了一些我不理解的行为 我在函数之前定义变量并将其作为参数传入,方法附加到引用,但在外部,name仍然未定义 var name; (function(exports) { exports = {}; exports.method = function() { // do stuff }; })(name); alert(name === undefined); // true consol

我一直在试验通过自调用匿名函数将方法和变量附加到对象的方法,但遇到了一些我不理解的行为

我在函数之前定义变量并将其作为参数传入,方法附加到引用,但在外部,
name
仍然未定义

var name;
(function(exports) {
    exports = {};
    exports.method = function() {
        // do stuff
    };
})(name);

alert(name === undefined); // true
console.log(name === undefined); // false
console.log(name.method); // undefined
但是当变量在函数外部初始化时,而不是在函数内部初始化时,会像我所期望的那样附加正确的属性

var name2 = {};
(function(exports) {
    exports.method = function() {
        // do stuff
    };
})(name2);

alert(name2 === undefined); // false
alert(name2.method); // method is defined

为什么?

因为对象是通过引用传递的,而未定义的变量不是。

当涉及到闭包时,将一个对象作为参数从函数范围之外传递给自执行函数是一个很方便的技巧,而闭包的作用是引用外部对象(在第一个示例中,
name
)中存储的引用是通过副本(即引用的副本)传递的

通过引用副本对对象进行的任何更改都将在功能之外产生影响,例如在第二个示例中

exports.method = function() {
    // do stuff
};
将方法添加到由name2标识的对象。 但是,如果像在中那样覆盖参数所保留的引用

exports = {}
然后,您只需将一个新引用存储在用于保存原始引用(副本)的同一个变量中

在使用闭包和迭代变量时需要复制技巧 e、 g


将打印0,1,2,3,4,5,6,7,8,9

在第一个示例中,您使用新对象覆盖对象的副本,然后为其分配一个方法。该对象和方法在函数外部不可用

在第二个示例中,您将变量定义为函数外部的对象,并且没有使用新对象覆盖引用。因此,该方法附加到传入的对象

如果要创建第三个示例,其中在函数外部定义变量,然后在函数内部覆盖对该变量的引用--

--您会发现该方法再次未定义

var name;
(function(exports) {
    exports = {};
    exports.method = function() {
        // do stuff
    };
})(name);

alert(name === undefined); // true
console.log(name === undefined); // false
console.log(name.method); // undefined
在第一个示例中,“name”和“exports”共享指向undefined的指针,直到指定“exports”指向空对象,但“name”仍然指向undefined

var name;
(function(exports) {
    exports = {};
    exports.method = function() {
        // do stuff
    };
})(name);

alert(name === undefined); // true
console.log(name === undefined); // false
console.log(name.method); // undefined

在第二个示例中,“名称”和“导出”共享指向对象的指针。稍后该对象被修改为具有新属性,但两个变量的指针仍然相同。

No.
undefined
也是一个对象引用。您只是用另一个引用覆盖引用。实际上,对象作为引用的副本传递给函数,这是一个很大的区别。@Qundefined不是一个对象引用,它是一个原始值类型。你可以说它是一个不可解析的引用(
isUnsolvableReference
-true),但这听起来很违反直觉。Dan-所有的东西都是按值传递的,当你传递一个引用时,你就传递它的值。这就是为什么
var a={a:3};(函数(x){x={b:5})(a);a;
将返回
{a:3}
例如,我对回答你自己的问题没有问题,但你为什么在问题中写“我不明白”?他学得很快…?是的,我刚做完问题就想出来了。下层选民会给我一些东西继续吗?只要评论一下我如何改进这个问题就好了。是的,我们是。奥德尔y、 当我创建一个fiddle时,它的性能与您描述的一样,但是当我在Firebug的控制台中运行它时……啊,没关系,我只是看到了我犯的复制粘贴错误。示例中没有闭包,因为所讨论的对象是作为参数传递给函数的,我认为您的意思是“将对象分配给变量”,而不是“将变量定义为对象”因为你不能将变量定义为对象。是的,我正在编辑过程中,在你发表评论时被人打断。回答得很好,例子也很好。干杯!