1

我在另一个线程上被告知,在函数退出后,从函数内部对其操作数所做的任何修改都将持续存在。我一直认为它对传递给它的所有值做了一个临时副本,然后唯一保留的东西是返回值和被修改的隐式更广泛范围的变量。

我想回想一下我在其源代码中达到顶峰的所有 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.

有人能解释一下参数传递是如何工作的吗?我以为我知道它是怎么做到的,但我想我不知道。谢谢

4

3 回答 3

1

它实际上非常简单:Javascript 中的每个名称都指向内存中的一个对象(即使您不以面向对象的方式考虑它)——它是内存中该“元素”的数据结构所在的位置。

因此,如果传递的值是一个像数组这样的对象,或者其他具有属性和名称的元素,那么您在函数中得到的是同一个对象。如果您更改它的属性(如p.n = p.n + 1上面的示例),因为“p”对象在函数内部和外部是相同的。

现在,当您执行: 时p = p + 1,由名称引用的原始对象p被替换为另一个对象 - 在表达式中创建的对象,其值为 p + 1. 函数内部的名称p指向另一个对象,完全位于另一个内存位置,而原始对象则传递给函数,并且名称x中的引用保持不变。

例如,这种机制与 Python 语言中的机制完全相同。

于 2012-09-22T01:29:54.407 回答
1

当你有:

p.n = p.n + 1;

您正在做的是修改在引用n的对象中调用的属性。换句话说,可以看成是一个指向对象的指针,也就是说,它持有对你已经传递给函数的引用值的原始对象的引用另一方面,当你有:pp

p = p + 1;

您只是用计算表达式的结果替换持有的对象引用值。您没有修改对象的任何属性。pp + 1p

于 2012-09-22T01:23:25.287 回答
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是该函数内部的一个新私有变量,它只有函数范围。

于 2012-09-22T01:35:33.417 回答