基元类型(数字、字符串等)是通过值传递的,但对象是未知的,因为它们既可以通过值传递(如果我们认为持有对象的变量实际上是对对象的引用),也可以通过引用传递(当我们认为对象的变量持有对象本身)。

虽然最后这并不重要,但我想知道通过约定来表达论点的正确方式是什么。是否有JavaScript规范的摘录,该规范定义了与此相关的语义?


当前回答

它总是按值传递,但对于对象,变量的值是一个引用。因此,当您传递一个对象并更改其成员时,这些更改将在函数之外持续存在。这使得它看起来像是通过引用传递。但如果您实际更改了对象变量的值,您将看到更改不会持续,这证明它确实是通过值传递的。

例子:

函数changeObject(x){x={member:“bar”};console.log(“in changeObject:”+x.member);}函数changeMember(x){x.member=“bar”;console.log(“in changeMember:”+x.member);}var x={member:“foo”};console.log(“before changeObject:”+x.member);changeObject(x);console.log(“after changeObject:”+x.member);/*更改没有持续*/console.log(“changeMember之前:”+x.member);changeMember(x);console.log(“after changeMember:”+x.member);/*更改持续存在*/

输出:

before changeObject: foo
in changeObject: bar
after changeObject: foo

before changeMember: foo
in changeMember: bar
after changeMember: bar

其他回答

JavaScript按值传递原语类型,按引用传递对象类型

现在,人们喜欢没完没了地争论是否“通过引用”是描述Java等实际操作的正确方式这是:传递对象不会复制对象。传递给函数的对象可以由该函数修改其成员。传递给函数的基元值不能由该函数修改。复制完成。在我的书中,这叫做通过引用传递。

-Brian Bi-哪些编程语言是通过引用传递的?


使现代化

以下是对此的反驳:

JavaScript中没有可用的“通过引用传递”。

“JavaScript:最终指南”一书的这一章对复制、传递和比较值和引用进行了非常详细的解释。

在我们离开主题之前操作对象和阵列参考,我们需要澄清一点术语。短语“路过”“引用”可以有几种含义。对一些读者来说,这个短语指的是一种函数调用技术允许函数分配新值它的论点,并拥有这些外部可见的修改值作用这不是术语的方式本书中使用了。这里,我们的意思是简单地说,对对象的引用或数组--而不是对象本身--传递给函数。A函数可以使用引用修改对象或元素的财产阵列的。但如果函数用对新对象或阵列的引用,该修改不可见在功能之外。读者熟悉这个词可能更喜欢这样说对象和数组值,但传递的值为实际上是一个参考,而不是对象本身。

我发现Undercore.js库的extend方法非常有用,当我想将一个对象作为一个参数传递时,它可以被修改或完全替换。

function replaceOrModify(aObj) {
  if (modify) {

    aObj.setNewValue('foo');

  } else {

   var newObj = new MyObject();
   // _.extend(destination, *sources) 
   _.extend(newObj, aObj);
  }
}

观察:如果观察者无法检查引擎的底层内存,则无法确定是否复制了不可变值或传递了引用。

JavaScript或多或少与底层内存模型无关。没有参考²。JavaScript有值。两个变量可以保持相同的值(或者更准确:两个环境记录可以绑定相同的值)。唯一可以变异的值类型是通过抽象[[Get]]和[[Set]]操作的对象。如果您忘记了计算机和内存,这就是描述JavaScript行为所需的全部内容,它可以让您理解规范。

 let a = { prop: 1 };
 let b = a; // a and b hold the same value
 a.prop = "test"; // The object gets mutated, can be observed through both a and b
 b = { prop: 2 }; // b holds now a different value

现在你可能会问自己,两个变量如何在计算机上保持相同的值。然后,您可能会查看JavaScript引擎的源代码,很可能会发现引擎所用语言的程序员会调用引用。

所以事实上,你可以说JavaScript是“值传递”,而值可以被共享,你可以称JavaScript是“引用传递”,这对于低级语言的程序员来说可能是一个有用的逻辑抽象,或者你可以将行为称为“共享调用”。

由于JavaScript中没有引用,所有这些都没有错,也没有切中要害。因此,我不认为搜索答案特别有用。

²规范中的术语“参考”不是传统意义上的参考。它是一个对象和属性名称的容器,并且是一个中间值(例如,a.b计算为Reference{value=a,name=“b”})。术语“引用”有时也出现在规范中的不相关章节中。

JavaScript总是按值传递;一切都是价值型的。

对象是值,对象的成员函数本身是值(请记住,函数是JavaScript中的一级对象)。此外,关于JavaScript中的一切都是一个对象的概念;这是错误的。字符串、符号、数字、布尔值、空值和未定义值都是基元。

有时,他们可以利用从基本原型继承的一些成员函数和财产,但这只是为了方便。这并不意味着它们本身就是对象。请尝试以下操作以供参考:

x=“测试”;console.log(x.foo);x.foo=12;console.log(x.foo);

在两个console.log中,您都会发现值未定义。