Javascript是否通过引用传递?

J A*_*Any 340 javascript reference pass-by-reference pass-by-value

Javascript是通过引用传递还是通过值传递?以下是Javascript:Good Parts的示例.我my对矩形函数的参数非常困惑.它实际上是undefined在函数内部重新定义的.没有原始参考.如果我从函数参数中删除它,则内部区域功能无法访问它.

是关闭吗?但是没有返回任何函数.

var shape = function (config) {
    var that = {};
    that.name = config.name || "";
    that.area = function () {
        return 0;
    };
    return that;
};
var rectangle = function (config, my) {
    my = my || {};
    my.l = config.length || 1;
    my.w = config.width || 1;
    var that = shape(config);
    that.area = function () {
        return my.l * my.w;
    };
    return that;
};
myShape = shape({
    name: "Unhnown"
});
myRec = rectangle({
    name: "Rectangle",
    length: 4,
    width: 6
});
console.log(myShape.name + " area is " + myShape.area() + " " + myRec.name + " area is " + myRec.area());
Run Code Online (Sandbox Code Playgroud)

Aln*_*tak 631

基元按值传递,对象通过"引用副本"传递.

具体来说,当您传递一个对象(或数组)时,您(无形地)传递对该对象的引用,并且可以修改该对象的内容,但是如果您尝试覆盖该引用,它将不会影响该对象的副本调用者持有的引用 - 即引用本身按值传递:

function replace(ref) {
    ref = {};           // this code does _not_ affect the object passed
}

function update(ref) {
    ref.key = 'newvalue';  // this code _does_ affect the _contents_ of the object
}

var a = { key: 'value' };
replace(a);  // a still has its original value - it's unmodfied
update(a);   // the _contents_ of 'a' are changed
Run Code Online (Sandbox Code Playgroud)

  • 虽然不受欢迎,但对象的行为通常被命名为"通过共享呼叫":http://en.wikipedia.org/wiki/Call_by_sharing#Call_by_sharing (12认同)
  • @IoanAlexandruCucu 我个人认为“参考副本”更直观;-) (8认同)
  • @Inverse 我回滚了你的编辑,因为它_完全改变了它的语义_。对如此高票的答案做出如此实质性的改变也是完全不合适的! (5认同)
  • 如果您打算使用短语"引用副本",那么您也可以将原语称为"值的副本".这就是为什么两者实际上只是"按价值传递".两者都传递值的副本,无论该值是数字,bool,字符串还是引用. (3认同)

jAn*_*ndy 58

可以这样想:

每当你在ECMAscript中创建一个对象时,这个对象就形成了一个神秘的ECMAscript通用的地方,没有人能够得到它.你得到的只是在这个神秘的地方引用那个对象.

var obj = { };
Run Code Online (Sandbox Code Playgroud)

甚至obj只是对象的引用(位于那个特别美妙的地方),因此,你只能传递这个引用.实际上,访问obj的任何代码都将修改远离的对象.

  • 并且*reference*本身通过值*传递*,就像JavaScript中的其他所有内容一样. (32认同)
  • @jAndy 在这次交流中,我有点病态地意识到人们会在我离开这个世界很久之后对我的回答和评论发表评论,这让我感到震惊。 (3认同)
  • @Pointy 参考的价值是什么?引用是一种类型吗?我认为这个文字游戏毫无用处。 (2认同)
  • @albanx 我意识到这令人沮丧,但每个专业领域都有专门的术语。“引用”的意思类似于 C 或 C++ 中的“指针”的意思(C++ 有指针 * 和 * 引用)。然而,在 JavaScript 或 Java 之类的语言中,作为特定对象的“值”只能是该对象的*引用*。所以它不是一种类型,实际上,它是对实际值的表征。 (2认同)
  • @albanx 我会将这个观点转达给 2012 年的我:) (2认同)

Ray*_*rea 41

我的2分钱...... Javascript是通过引用还是值传递参数无关紧要.真正重要的是分配与变异.

我在这里写了一个更长,更详细的解释(JavaScript是通过引用传递还是按值传递的语言?)

当你传递任何东西时(无论是对象还是原始),所有javascript都会在函数内部分配一个新变量...就像使用等号(=)一样

该函数在函数内的行为方式与您使用等号分配新变量时的行为完全相同.请参考这些简单示例.

var myString = 'Test string 1';

// Assignment - A link to the same place as myString
var sameString = myString;

// If I change sameString, it will not modify myString, 
// it just re-assigns it to a whole new string
sameString = 'New string';

console.log(myString); // logs 'Test string 1';
console.log(sameString); // logs 'New string';
Run Code Online (Sandbox Code Playgroud)

如果我将myString作为参数传递给函数,它就像我只是将它分配给一个新变量一样.现在,让我们做同样的事情,但是使用函数而不是简单的赋值

function myFunc(sameString) {

    // Re assignment.. again, it will not modify myString
    sameString = 'New string';
}

var myString = 'Test string 1';

// This behaves the same as if we said sameString = myString
myFunc(myString);

console.log(myString); // Again, logs 'Test string 1';
Run Code Online (Sandbox Code Playgroud)

将对象传递给函数时可以修改对象的唯一原因是因为您没有重新分配...而是可以更改或改变对象....再次,它的工作方式相同.

var myObject = { name: 'Joe'; }

// Assignment - We simply link to the same object
var sameObject = myObject;

// This time, we can mutate it. So a change to myObject affects sameObject and visa versa
myObject.name = 'Jack';
console.log(sameObject.name); // Logs 'Jack'

sameObject.name = 'Jill';
console.log(myObject.name); // Logs 'Jill'

// If we re-assign it, the link is lost
sameObject = { name: 'Howard' };
console.log(myObject.name); // Logs 'Jill'
Run Code Online (Sandbox Code Playgroud)

如果我将myObject作为参数传递给函数,它就像我只是将它分配给一个新变量一样.同样,具有完全相同的行为但具有功能的相同事物.

function myFunc(sameObject) {

    // We mutate the object, so the myObject gets the change too... just like before.
    sameObject.name = 'Jill';

    // But, if we re-assign it, the link is lost
    sameObject = { name: 'Howard' };
}

var myObject = { name: 'Joe'; }

// This behaves the same as if we said sameObject = myObject;
myFunc(myObject);
console.log(myObject.name); // Logs 'Jill'
Run Code Online (Sandbox Code Playgroud)

每次将变量传递给函数时,您都会"分配"参数的名称,就像使用等号(=)一样.

永远记住,等号(=)表示赋值.将参数传递给函数也意味着赋值.它们是相同的,2个变量以完全相同的方式连接.

修改变量影响不同变量的唯一时间是基础对象发生变异时.

在对象和基元之间进行区分是没有意义的,因为它的工作方式与没有函数的情况完全相同,只是使用等号分配给新变量.

  • 它就是“通过副本传递”和“通过引用传递”,就这么简单地传达了所有相关的含义。我得到的是“一件东西就是它自己的东西”还是“东西”就是你关心的一切。 (2认同)
  • 很好的解释雷! (2认同)

小智 20

函数参数按值传递或按共享传递,但永远不会在Javascript中通过引用传递!

呼叫按值

原始类型按值传递:

var num = 123, str = "foo";

function f(num, str) {
  num += 1;
  str += "bar";
  console.log("inside of f:", num, str);
}

f(num, str);
console.log("outside of f:", num, str);
Run Code Online (Sandbox Code Playgroud)

功能范围内的重新分配在周围范围内不可见.

这也适用于Strings,它是复合数据类型但不可变:

var str = "foo";

function f(str) {
  str[0] = "b"; // doesn't work, because strings are immutable
  console.log("inside of f:", str);
}

f(str);
console.log("outside of f:", str);
Run Code Online (Sandbox Code Playgroud)

调用 - 共享

对象,也就是说所有不是基元的类型都是通过共享传递的.保存对象引用的变量实际上只包含此引用的副本.如果Javascript将采用逐个引用的评估策略,则该变量将保留原始引用.这是副共享和引用之间的关键区别.

这种区别的实际后果是什么?

var o = {x: "foo"}, p = {y: 123};

function f(o, p) {
  o.x = "bar"; // mutation
  p = {x: 456}; // reassignment
  console.log("o inside of f:", o);
  console.log("p inside of f:", p);
}

f(o, p);

console.log("o outside of f:", o);
console.log("p outside of f:", p);
Run Code Online (Sandbox Code Playgroud)

变异意味着修改现有的某些属性Object.变量绑定到的引用副本以及引用此对象的引用副本保持不变.因此,在调用者的范围内可以看到突变.

重新分配意味着替换绑定到变量的引用副本.由于它只是一个副本,因此保存相同引用副本的其他变量不受影响.因此,在呼叫者的范围内,重新分配不像在参考呼叫评估策略中那样可见.

有关Ecmascript 评估策略的更多信息.


jmo*_*eno 18

与C一样,最终,一切都按价值传递.与C不同,您实际上无法备份并传递变量的位置,因为它没有指针只是引用.

它所引用的都是对象,而不是变量.有几种方法可以实现相同的结果,但必须手动完成,而不仅仅是在调用或声明站点添加关键字.

  • 这实际上是这里最正确的答案.如果你深入研究V8或竞争引擎,这就是实际实现函数调用的方式. (3认同)

yal*_*lam 7

JavaScript是按值传递的.对于原语,传递原始值.对于Objects,传递Object的引用"value".

对象示例:

var f1 = function(inputObject){
    inputObject.a=2;
}
var f2 = function(){
    var inputObject={"a":1};
    f1(inputObject); 
    console.log(inputObject.a);
}
Run Code Online (Sandbox Code Playgroud)

调用f2导致打印出"a"值为2而不是1,因为传递了引用并且更新了引用中的"a"值.

原语示例:

var f1 = function(a){
    a=2;
}
var f2 = function(){
    var a =1;
    f1(a); 
    console.log(a);
}
Run Code Online (Sandbox Code Playgroud)

调用f2会导致打印出"a"值为1.


小智 5

实际上,Alnitak 是正确的并且易于理解,但最终在 JavaScript 中,一切都是按值传递的。

物体的“价值”是什么?它是对象引用。

当您传入一个对象时,您将获得该值的副本(因此称为 Alnitak 所描述的“引用的副本”)。如果更改此值,则不会更改原始对象;您正在更改该参考的副本。

  • 这并没有澄清而是令人困惑。 (5认同)

4m1*_*m1r 5

为了创建一个使用 const 的简单示例......

const myRef = { foo: 'bar' };
const myVal = true;

function passes(r, v) {
  r.foo = 'baz';
  v = false;
}

passes(myRef, myVal);

console.log(myRef, myVal); // Object {foo: "baz"} true
Run Code Online (Sandbox Code Playgroud)