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通行证
数组和对象根据这两个条件作为传递引用或传递值传递。
如果用新对象或数组更改该对象或数组的值,则它是传递值。
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 |