简体   繁体   English

通过引用传递 JavaScript 对象

[英]Pass-by-reference JavaScript objects

Please read the comments in the code below to know what I am trying to ask.请阅读下面代码中的注释以了解我要问的内容。

Expected Output: As per pass-by-reference mechanism in JavaScript, objOne is expected to log {} at the end, because objTwo was initialized with {} .预期的 Output:根据 JavaScript 中的传递引用机制, objOne应该在最后记录{} ,因为objTwo是用{}初始化的。

var objOne = {
  x: 1,
  y: 2
};

var objTwo = objOne;

// change the x vlaue to 2 by objTwo
objTwo.x = 2;

// Change the value of key x in objOne as well - pass by reference mechanism
console.log(objOne); // { x: 2, y: 2 }

/*** Pass by reference is understood in code, above this comment ***/

// Now what if objTwo initialized with empty object
objTwo = {};

console.log(objOne); // { x: 2, y: 2 } but expected output = {}

// As per pass by reference mechanism. objOne is expected to log {}, because objTwo was initialized with {}.

When you assign one variable to another, it's not that both those variables are now linked by reference; 当您将一个变量分配给另一个变量时,并不是这两个变量现在都已通过引用链接在一起。 you're misunderstanding what "pass by reference" means here. 您误解了“通过​​引用”在这里的含义。

A variable holding an object does not "directly" hold an object. 保存对象的变量不会“直接”保存对象。 What it holds is a reference to an object . 它持有的是对对象引用 When you assign that reference from one variable to another, you're making a copy of that reference. 当您将该引用从一个变量分配给另一个变量时,就是在复制该引用。 Now both variables hold a reference to an object. 现在,两个变量都拥有对对象的引用。 Modifying the object through that reference changes it for both variables holding a reference to that object. 通过该引用修改对象会更改持有该对象引用的两个变量。

When you assign a new value to one of the variables, you're just modifying the value that variable holds. 当您将新值分配给其中一个变量时,您只是在修改该变量保存的值。 The variable now ceases to hold a reference to the object, and instead holds something else. 现在,变量不再保留对对象的引用,而是保留其他内容。 The other variable still holds its reference to the original object, the assignment didn't influence it at all. 另一个变量仍然保留其对原始对象的引用,分配完全不影响它。

When you evaluate 当你评估

objTwo = {};

Javascript interprets that as reassigning objTwo to a new literal empty object, and leaves its old value alone. Javascript将其解释为将objTwo重新分配给新的文字空对象,而将其旧值保留下来。

If you want to remove a key from objOne by reference, you can use the delete keyword: 如果要通过引用从objOne中删除键,则可以使用delete关键字:

delete objTwo.x;  // also deletes the x property of objOne

When 2 variables are pointing to same object, it doesn't mean that they're now magically 'tied' to each other. 当两个变量指向同一个对象时,这并不意味着它们现在就彼此魔术地“绑在一起”了。

In your case, objTwo = {} is simply changing objTwo to point at the new object you created. 在您的情况下, objTwo = {}只是将objTwo更改为指向您创建的新对象。

objTwo = {}; doesn't work the way you think it works. 无法按照您认为的方式工作。 I usually recommend thinking of variables as "pointers". 我通常建议将变量视为“指针”。

objOne and objTwo are two totally different variables. objOneobjTwo是两个完全不同的变量。 When you did objTwo = {}; 当您完成objTwo = {}; , what it did was have the objTwo variable point to another object. ,它所做的就是让objTwo变量指向另一个对象。 It does not alter the objOne variable. 它不会更改objOne变量。

Let's visualize: 让我们想象一下:

var objOne = {
  x: 1,
  y: 2
};

// objOne -> { x: 1, y: 2 }

var objTwo = objOne;

// objOne -> { x: 1, y: 2 } <- objTwo

objTwo.x = 2;

// objOne -> { x: 2, y: 2 } <- objTwo (update object via objTwo variable)

objTwo = {};

// objOne -> { x: 2, y: 2 }, objTwo -> {}

JavaScript通过引用传递的方式有所不同,只要更改对象的属性(如obj.x = 1),对象就被视为引用,但是对象变量本身(obj = [])的分配会将其视为基于值的对象变量。

only delete can call initialize state .. 只有删除才能调用初始化状态。

for(var i in objOne){
    delete objOne[i];
}

@nrabinowitz saying @nrabinowitz说

  • Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object. Javascript总是按值传递,但是当变量引用对象(包括数组)时,“值”是对对象的引用。
  • Changing the value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object. 更改变量的值永远不会更改基础原语或对象,而只是将变量指向新的原语或对象。
  • However, changing a property of an object referenced by a variable does change the underlying object. 但是,更改变量引用的对象的属性确实会更改基础对象。

I agree with accepted answer, this is just some code to back it up. 我同意接受的答案,这只是一些支持它的代码。

let objOne = {x: 1, y: 2};
let objTwo = objOne; // referencing to same thing

objTwo.x = 2;
console.log(objOne, objTwo); // output {x:2, y:2}, {x:2, y:2}

let objThree = {};
objTwo = objThree; // notice this. Same as "objTwo = {}", except now you have objThree as initial reference
console.log(objOne, objTwo, objThree); // output {x:2, y:2}, {}, {}

You can easily notice what happened by changing objTwo reference or adding it complete new value as it was shown in question example. 您可以通过更改objTwo引用或将其完整添加为问题示例中显示的新值来轻松地注意到发生了什么。

As per pass-by-reference mechanism in JavaScript根据 JavaScript 中的传递引用机制

Let's get this out of the way: there is no pass-by-reference mechanism in JavaScript.让我们解决这个问题:JavaScript 中没有传递引用机制。 Pass-by-reference is a very specific feature.引用传递是一个非常具体的功能。 To know whether a language supports it, you should check whether it is possible to pass a variable with an immutable value to a function (for instance an integer), and after that call see that this variable has a different immutable value.要知道一种语言是否支持它,您应该检查是否可以将具有不可变值的变量传递给 function(例如整数),然后在调用之后看到该变量具有不同的不可变值。 If this is not possible, then the language does not support pass-by-reference.如果这不可能,则该语言不支持传递引用。 JavaScript does not support it. JavaScript 不支持。 C does not support it. C 不支持。 C++ does support it (by declaring a function parameter with & ). C++确实支持它(通过用&声明 function 参数)。

As to your code example;至于您的代码示例; let's visualise it.让我们形象化它。

First phase第一阶段

After the first two var statements we get this:在前两个var语句之后,我们得到:

objOne
  ↓  
┌───────────┐
│ x: 1      │
│ y: 2      │
└───────────┘
  ↑  
objTwo

Only one object was created (using object literal syntax).仅创建了一个 object(使用 object 文字语法)。

After objTwo.x = 2 , we get:objTwo.x = 2之后,我们得到:

objOne
  ↓  
┌───────────┐
│ x: 2      │
│ y: 2      │
└───────────┘
  ↑  
objTwo

Only one property value was changed, in the only object that was created.在创建的唯一 object 中,仅更改了一个属性值。 Whether you look at the object via variable objOne or objTwo does not make a difference.无论您是通过变量objOne还是objTwo都没有区别。

Second phase第二阶段

objTwo = {} creates a second object and assigns its reference to objTwo . objTwo = {}创建第二个object 并将其引用分配给objTwo Now we have two, distinct objects:现在我们有两个不同的对象:

objOne
  ↓  
┌───────────┐
│ x: 2      │
│ y: 2      │
└───────────┘

objTwo
  ↓  
┌───────────┐
└───────────┘

You cannot change which object objOne is referencing without making an assignment to objOne .您无法更改objOne引用的objOne而不对objOne进行分配 Even though objOne and objTwo first referenced the same object, these variables are still distinct references.尽管objOneobjTwo首先引用了同一个 object,但这些变量仍然是不同的引用。 In the first phase we saw we can mutate the object that objOne references, but it is still the same object -- just one that was subject to some mutation.在第一阶段,我们看到我们可以对objOne引用的 object 进行变异,但它仍然是相同的 object —— 只是发生了一些变异。 It is not possible to make objOne reference another object by making an assignment to objTwo .无法通过对 objTwo 进行赋值来使objOne引用另一个objTwo You really need to assign to objOne to make that happen.您确实需要分配给objOne才能实现。

Conclusion结论

There is no pass-by-reference mechanism in JavaScript. JavaScript 中没有传递引用机制。 In JavaScript objects are accessed and manipulated through references.在 JavaScript 中,对象通过引用进行访问和操作。 objTwo is not an alias for objOne , it only is a duplicate reference for the same object. objTwo不是objOne别名,它只是同一个 object 的重复引用。 As soon as another reference is assigned to objTwo , we have two distinct references.一旦将另一个引用分配给objTwo ,我们就有两个不同的引用。

This is how pass-by-reference works. 这就是引用传递的工作方式。 Here objTwo is referring to objOne so whatever you do with objTwo will also happen with objOne . 这里objTwo指的是objOne所以无论你做objTwo还将与objOne发生。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM