另一个线程告诉我,在函数退出后,从函数内对其操作数进行的任何修改都将持续存在。我一直认为它是传递给它的所有值的临时副本,然后唯一坚持的是返回值和隐式更广泛的已修改的范围变量。
我想回想一下我已经达到顶峰的所有jquery插件,他们都使用了构造:
(function($){
$.fn.foo = function(){ console.log('foo'); };
})(jQuery);
这意味着即使是内部作用域jQuery
标识符对$
对象的修改在函数退出后仍然存在,或者jQuery插件不起作用。因此,这可以像上面的代码片段那样工作:
var x = {n:0};
(function addOneTo(p) {
p.n = p.n + 1;
})(x);
console.log(x);
但是这个:
var x = 0;
(function addOneTo(p) {
p = p + 1;
})(x);
console.log(x);
不会,x
未修改,其值为0
。
有人可以解释一下参数传递的工作原理吗?我以为我知道它是怎么做的,但我想我不知道。感谢
答案 0 :(得分:1)
当你有:
p.n = p.n + 1;
您正在做的是修改在{strong>引用对象n
中的p
属性到p
。换句话说,p = p + 1;
可以看作是指向对象的指针,也就是说,它将引用保存到原始对象,该对象的参考值已传递给函数。另一方面,当你有:
p
您只需替换 p + 1
所持有的对象参考值,并评估表达式p
的结果。您不修改{{1}}对象的任何属性。
答案 1 :(得分:1)
实际上非常简单:Javascript中的每个名称都指向内存中的一个对象(即使你没有以面向对象的方式思考它) - 它是内存中的一个位置,其中该元素的数据结构“是。
因此,如果传递的值是一个像数组的对象,或者其他具有属性和名称的元素,那么你在函数中得到的就是同一个对象。如果你改变了它的属性(比如上面的p.n = p.n + 1
例子),因为“p”对象在内部是相同的而且在函数之外。
现在,执行:p = p + 1
时,名称为p
引用的原始对象将替换为另一个对象 - 在表达式中创建的对象,其值为{{ 1}}。函数内部的名称p + 1
指向另一个对象,完全位于另一个内存位置,原始的一个传递给函数,而名称为p
的引用则保持不变。
这种机制与Python语言完全相同,例如。
答案 2 :(得分:1)
实际上在你的第一个例子中
var x = {n:0};
(function addOneTo(p) {
p.n = p.n + 1;
})(x);
console.log(x);
x
是一个对象,当你使用p.n = p.n + 1;
时,它修改了原始对象的属性,因为它作为引用传递(p是与x相同的对象),但是在你的第二个例子中
var x = 0;
(function addOneTo(p) {
p = p + 1;
})(x);
console.log(x);
x
通过值传递给函数,p = p + 1;
此处p
是该函数内的新私有变量,它只有函数范围。