javascript返回对数组项的引用

fuy*_*uyi 13 javascript arrays pass-by-reference

我有一个像这样的数组:

users = [{id:1, name:'name1'},{id:2, name:'name2'}]
Run Code Online (Sandbox Code Playgroud)

我怎样才能获得对项{id:2,name:'name2'}的引用,所以我可以将其更改为name属性,如:

user = get_item(users, 'id', 2);
user.name = "user2 name changed";
Run Code Online (Sandbox Code Playgroud)

console.log(用户)将得到结果:

[{id:1, name:'name1'},{id:2, name:'user2 name changed'}]
Run Code Online (Sandbox Code Playgroud)

我尝试使用Array.filter()函数,但它返回一个新数组而不是对原始数组的引用.我不能用来改变原始数组.

任何的想法?

T.J*_*der 32

我试图使用Array.filter()函数,但它返回一个新数组而不是对原始数组的引用.我不能用来改变原始数组.

它返回一个新数组,但数组的条目仍然是对相同对象的引用.所以filter这很好.

var filteredUsers = users.filter(function(entry) { return entry.id === 2; });
var item = filteredUsers[0];
item.name = "user2 name updated";
console.log(users[1].name) // "user2 name updated"
Run Code Online (Sandbox Code Playgroud)

该数组包含对象的引用,而不是它们的副本.当我们这样做item = users[1]或者用于filter获取包含对象子集的新数组时,我们得到对象引用的副本,因此变量现在引用同一个对象,如下所示:

+-------+
| users |
+-------+          
|   0   |--------->+---------------+
|       |          | id:   1       |
|       |          | name: "name1" |          +---------------+
|       |          +---------------+          | filteredUsers |
|       |                                     +---------------+
|   1   |--------->+---------------+<---------|       0       |
|       |          | id:   2       |          +---------------+
|       |          | name: "name2" |
|       |          |               |          +------+
|       |          +---------------+<---------| item |
+-------+                                     +------+

更改对象会更改对象,无论对用于查看其属性的对象的哪个引用,这些更改都是可见的.

现在,如果你有一个基元数组:

var a = [1, 2, 3, 4, 5];
Run Code Online (Sandbox Code Playgroud)

...当然,你不能使用上面的方法,因为它们不是对象.在这种情况下,您将用于indexOf查找索引:

var index = a.indexOf(3); // Find the first entry === 3
Run Code Online (Sandbox Code Playgroud)

...然后修改条目

a[index] = 42;
Run Code Online (Sandbox Code Playgroud)

这也适用于字符串(前提是它们是很好的普通字符串原语,而不是你创建的东西new String(),实际上从来没有理由这样做).


say*_*iju 12

要做到与接受的答案类似,但更简洁一点,让我们使用Array.find,如下所示:

var item = users.find(u => u.id === 2)
item.name = "user2 name updated"
console.log(users[1].name) // "user2 name updated"
Run Code Online (Sandbox Code Playgroud)

解释与已接受的答案中提供的内容非常相似.

  • 我相信这是正确的答案,简短易行:) (2认同)

cam*_*ice 6

与 @zing-lee 的答案类似,您可以使用以下方法再删除一行代码find()

var users = [{id:1, name:'name1'},{id:2, name:'name2'}]
var user = users.find(item => item.id === 2)
user.name = 'name change'
Run Code Online (Sandbox Code Playgroud)

来自文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

返回值:数组中满足提供的测试函数的第一个元素的值

因为它是一个对象数组(而不是基元),所以返回的值将是对原始对象的引用,因此修改返回对象的属性将更新它所引用的对象的属性。

这里有一篇好文章解释了 Javasript 中的值和引用:https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0

  • 有趣的是,如果我使用像这样的扩展运算符覆盖基金方法找到的对象`letfoundElement = collections.find(element =&gt; element.id === someId); foundElement = {..someData};` 它不会工作 (2认同)
  • 这是预期的行为。展开运算符的工作方式类似于“Object.assign()”。它总是返回对象的浅表副本。 (2认同)

小智 5

您可以使用findIndex(),例如:

var users = [{id:1, name:'name1'},{id:2, name:'name2'}]
var idx = users.findIndex(item => item.id === 2);
var u = users[idx]; // the reference of user2
u.name = "name changed."; // same as `users[idx].name = "name changed.";`
Run Code Online (Sandbox Code Playgroud)