【问题标题】:mutation inside a function in javascriptjavascript中函数内部的突变
【发布时间】:2016-02-01 14:39:20
【问题描述】:

n00b 问题在这里:

假设你调用一个函数来更新这样的数字或字符串

var x = "well";
var helloify = function(str){
  str += "hello"
};

我希望这种行为:

helloify(x);
console.log(x)
\\ "well hello"

但是我得到了

\\ "well"

“+=”不会改变“x”的值吗?这种变化是否只存在于函数的范围内而不存在于全局环境中?

谢谢!

--困惑

【问题讨论】:

  • ""+=" 不会改变 "x" 的值吗?" 在这种情况下不是。它改变了str 的值。但是,str 只是复制了x 的值。这两个变量是完全独立的,彼此不知道。
  • Primitives 是按值传递的,也就是说你进入一个函数实际上是一个外部原始值的副本。

标签: javascript scope mutation


【解决方案1】:

当您调用helloify(x); 时,您将x(字符串)的(而不是引用)传递给x

str += "hello" 修改 str 并单独留下 x


注意:对象只能通过引用来寻址,因此如果x 是对对象的引用,那么您将修改由两个变量寻址的单个对象。简单的字符串虽然不是对象。

【讨论】:

  • 这似乎是一种令人困惑的方式来解释正在发生的事情。字符串是不可变的,因此 str += "hello" 创建一个新字符串并将该新字符串分配给 str 参数变量,该变量与最初传入的字符串无关。它的工作方式与传入一个对象一样一个字符串并将一个新对象分配给str。在内部,str 可能本质上是指向x 指向的相同字符串的指针(不是引用,而是指针)。分配给str 然后在str 变量中放置一个新的字符串指针。
  • @MariusMucenicu - 我不知道你在这里寻找什么魔法。 The spec 只是说它应用运算符,然后将结果分配回变量。仅供参考,您可以像我一样仔细阅读规范。
【解决方案2】:

这是因为参数的发送方式、字符串的处理方式以及 += 运算符的实际作用。

参数是按值发送的,所以该函数没有获取字符串变量,而是获取对字符串对象的引用的副本。

字符串是不可变的,这意味着您永远不会更改字符串对象1。当您更改字符串时,实际上会创建一个具有新值的新字符串。

str += "hello"str = str + "hello" 的缩写。这意味着它将创建一个值为str + "hello" 的新字符串,并将对该字符串对象的引用放入变量str

由于参数不是您发送到函数中的变量而是副本,因此为参数分配新字符串不会更改您在函数调用中使用的变量。


1 如果 Javascript 引擎知道该字符串将不再被使用,即当它可以安全地这样做同时保持不可变字符串的行为时,它实际上可能会更改字符串对象。

【讨论】:

    猜你喜欢
    • 2017-02-02
    • 2020-04-04
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-01
    相关资源
    最近更新 更多