按引用的javascript与按值的javascript

Javascript by reference vs. by value

本问题已经有最佳答案,请猛点这里访问。

我在寻找一些很好的综合阅读材料,比如当javascript通过值传递某个东西时,当通过引用传递某个东西时,以及当修改传递的项时,会影响函数外部的值,而当不影响时。我还感兴趣的是,当分配给另一个变量时,是通过引用还是通过值,以及它是否遵循任何不同于作为函数参数传递的规则。

我做了大量的搜索,找到了很多具体的例子(其中很多都是这样),从中我可以开始拼凑出一些真正的规则,但我还没有找到一个完整的、书面的文档来描述所有这些规则。

另外,语言中是否有控制某个东西是通过引用还是通过值传递的方法?

下面是一些我想理解的问题。这些只是例子-我实际上是想了解语言所遵循的规则,而不仅仅是特定例子的答案。但是,这里有一些例子:

1
2
3
4
5
6
7
8
9
10
function f(a,b,c) {
   a = 3;
   b.push("foo");
   c.first = false;
}

var x = 4;
var y = ["eeny","miny","mo"];
var z = {first: true};
f(x,y,z);

对于所有不同的类型,x、y和z的内容在f的范围之外是什么时候发生变化的?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function f() {
    var a = ["1","2","3"];
    var b = a[1];
    a[1] ="4";
    // what is the value of b now for all possible data types that the array in"a" might hold?
}

function f() {
    var a = [{yellow:"blue"}, {red:"cyan"}, {green:"magenta"}];
    var b = a[1];
    a[1].red ="tan";
    // what is the value of b now and why?
    b.red ="black";
    // did the value of a[1].red change when I assigned to b.red?
}

如果我想要一个对象的完全独立的副本(没有任何引用),那么最好的实践方法是什么?


我的理解是,这实际上非常简单:

  • javascript总是传递值,但是当一个变量引用一个对象(包括数组)时,"value"是对该对象的引用。
  • 更改变量的值不会更改基础原语或对象,它只是将变量指向新的原语或对象。
  • 但是,更改变量引用的对象的属性会更改基础对象。

因此,通过一些例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function f(a,b,c) {
    // Argument a is re-assigned to a new value.
    // The object or primitive referenced by the original a is unchanged.
    a = 3;
    // Calling b.push changes its properties - it adds
    // a new property b[b.length] with the value"foo".
    // So the object referenced by b has been changed.
    b.push("foo");
    // The"first" property of argument c has been changed.
    // So the object referenced by c has been changed (unless c is a primitive)
    c.first = false;
}

var x = 4;
var y = ["eeny","miny","mo"];
var z = {first: true};
f(x,y,z);
console.log(x, y, z.first); // 4, ["eeny","miny","mo","foo"], false

例2:

1
2
3
4
5
6
7
8
9
var a = ["1","2", {foo:"bar"}];
var b = a[1]; // b is now"2";
var c = a[2]; // c now references {foo:"bar"}
a[1] ="4";   // a is now ["1","4", {foo:"bar"}]; b still has the value
              // it had at the time of assignment
a[2] ="5";   // a is now ["1","4","5"]; c still has the value
              // it had at the time of assignment, i.e. a reference to
              // the object {foo:"bar"}
console.log(b, c.foo); //"2""bar"


javascript总是按值传递。但是,如果将对象传递给函数,"value"实际上是对该对象的引用,因此函数可以修改该对象的属性,但不会导致函数外部的变量指向其他对象。

一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function changeParam(x, y, z) {
  x = 3;
  y ="new string";
  z["key2"] ="new";
  z["key3"] ="newer";

  z = {"new" :"object"};
}

var a = 1,
    b ="something",
    c = {"key1" :"whatever","key2" :"original value"};

changeParam(a, b, c);

// at this point a is still 1
// b is still"something"
// c still points to the same object but its properties have been updated
// so it is now {"key1" :"whatever","key2" :"new","key3" :"newer"}
// c definitely doesn't point to the new object created as the last line
// of the function with z = ...


是的,javascript总是按值传递,但在数组或对象中,该值是对它的引用,因此您可以"更改"内容。

但是,我想你已经读过了;这里有你想要的文件:

http://snook.ca/archives/javascript/javascript通行证


  • 基本类型变量,如string,number始终作为pass传递按价值计算。
  • 数组和对象根据这两个条件作为传递引用或传递值传递。

    • 如果用新对象或数组更改该对象或数组的值,则它是传递值。

      object1 = {item:"car"};
      array1=[1,2,3];

    在这里,您要将新对象或数组分配给旧对象或数组。旧对象的。所以它是传递值。

    • 如果要更改对象或数组的属性值,则它是按引用传递的。

      object1.item="car";
      array1[0]=9;

    这里您正在更改旧对象的属性值。您没有将新对象或数组分配给旧对象或数组。因此它是按引用传递的。

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
        function passVar(object1, object2, number1) {

            object1.key1="laptop";
            object2 = {
                key2:"computer"
            };
            number1 = number1 + 1;
        }

        var object1 = {
            key1:"car"
        };
        var object2 = {
            key2:"bike"
        };
        var number1 = 10;

        passVar(object1, object2, number1);
        console.log(object1.key1);
        console.log(object2.key2);
        console.log(number1);

    Output: -
        laptop
        bike
        10