簡體   English   中英

Js Array.prototype.map() 碰巧是可變的?

[英]Js Array.prototype.map() happens to be mutable?

當 map 方法的最初目的是創建一個新數組時,為什么它會改變原始數組?

我有一個對象數組,我將其傳遞給一個純函數,該函數又映射給定數組並返回一個新數組。 然后我注意到原始數組也發生了變化。我理解 Js 中的對象是通過引用傳遞的概念,但仍然不能完全理解為什么map的實現會改變原始數組,這有點違背了 IMO 的目的。

var initialArray = [ { name: 'one' }, { name: 'two' }, { name: 'three'} ];

function doSomething(array) {

  // lodash
  // return _.map(array, (item) => _.assign(item, {isSelected: true}));  

  // vanilla
  return array.map(function(item) {
    item['isSelected'] = true;
    return item
  });

}

var changedArray = doSomething(initialArray);

console.log('initialArray', initialArray); // [{ name: 'one', isSelected: true }, ...]
console.log('changedArray', changedArray); // [{ name: 'one', isSelected: true }, ...]
console.log(initialArray === changedArray); // false

首先我想了解為什么會這樣?

其次,我想了解如何在不更改原始數組的情況下映射數組? (即每次在map感覺不對之前都做._cloneDeep

提前致謝 !

編輯

好的,據我了解,事情就是這樣。 我想我可能出於某種原因有更高的期望,但它在 Js 中是可以解釋的,所以至少有一些一致性。

我能想到的用新成員創建新數組的最優雅的解決方案是

return _.map(array, (item) => _.assign({}, ...item, {isSelected: true}));   

.map會創建一個新的數組,但是數組里面的對象仍然被引用。

因此,當您在 inside.map 函數中更改object item時,它會引用輸入數組中的原始對象。

修復它的一種方法是在修改它之前克隆每個對象

var initialArray = [ { name: 'one' }, { name: 'two' }, { name: 'three'} ];

function clone(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}

function doSomething(array) {

  // lodash
  // return _.map(array, (item) => _.assign(item, {isSelected: true}));  

  // vanilla
  return array.map(function(item) {
    var copy = clone(item);
    copy['isSelected'] = true;
    return copy;
  });

}

var changedArray = doSomething(initialArray);

console.log('initialArray', initialArray); // [{ name: 'one'}, ...]
console.log('changedArray', changedArray); // [{ name: 'one', isSelected: true }, ...]
console.log(initialArray === changedArray); // false

信用:克隆功能是從這篇文章中復制的

您修改通過引用 map 函數傳遞的 get 對象,而不是 get 映射的數組。 changedArrayinitialArray都包含相同的對象。

 var initialArray = [ { name: 'one' }, { name: 'two' }, { name: 'three'} ]; var initialArray2 = [ { name: 'one' }, { name: 'two' }, { name: 'three'} ]; function doSomething(array) { // vanilla return array.map(function(item) { item['isSelected'] = true; return item }); } function doSomethingElse(array){ return array.map(function( item ){ // return a new object don't change the initial one return { name: item.name, isSelected: true }; }); } var changedArray = doSomething(initialArray), differentObjectsInArray = doSomethingElse( initialArray2 ); console.assert( initialArray,== changedArray; 'both arrays are different' ). console,assert( initialArray[0];== changedArray[0]. 'both arrays are referencing different objects' ), console;assert( initialArray2[0].== differentObjectsInArray[0], 'both arrays are referencing different objects' ); console.log('initialArray', initialArray ); console.log('initialArray2', initialArray2 ); console.log('differentObjectsInArray', differentObjectsInArray );
 <script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>

當 map 方法的最初目的是創建一個新數組時,為什么它會改變原始數組?

我有一個對象數組,我將它傳遞給一個純函數,該函數又映射給定數組並返回一個新數組。 然后我注意到原始數組也發生了變化..我理解 Js 中的 Object 通過引用傳遞的概念,但仍然無法完全理解為什么map的實現會改變原始數組,有點超出了 IMO 的目的。

var initialArray = [ { name: 'one' }, { name: 'two' }, { name: 'three'} ];

function doSomething(array) {

  // lodash
  // return _.map(array, (item) => _.assign(item, {isSelected: true}));  

  // vanilla
  return array.map(function(item) {
    item['isSelected'] = true;
    return item
  });

}

var changedArray = doSomething(initialArray);

console.log('initialArray', initialArray); // [{ name: 'one', isSelected: true }, ...]
console.log('changedArray', changedArray); // [{ name: 'one', isSelected: true }, ...]
console.log(initialArray === changedArray); // false

首先我想了解為什么會發生這種情況?

第二個我想了解如何在不更改原始數組的情況下映射數組? (即每次在map感覺錯誤之前都執行._cloneDeep

提前致謝 !

編輯

好吧,據我所知,事情就是這樣。 我想我可能出於某種原因有更高的期望,但它在 Js 中是可以解釋的,所以至少有一些一致性。

我能想到的用新成員創建新數組的最優雅的解決方案是

return _.map(array, (item) => _.assign({}, ...item, {isSelected: true}));   

如果您只想解決 OP 的示例,那么您可以將item對象傳播到從Array.map()返回的新對象中。

 var initialArray = [ { name: 'one' }, { name: 'two' }, { name: 'three'} ]; function doSomething(array) { // lodash // return _.map(array, (item) => _.assign(item, {isSelected: true})); // vanilla return array.map(function(item) { return {...item, isSelected: true } }); } var changedArray = doSomething(initialArray); console.log('initialArray', initialArray); // initialArray [ { name: 'one' }, { name: 'two' }, { name: 'three' } ] console.log('changedArray', changedArray); // changedArray [ { name: 'one', isSelected: true }, { name: 'two', isSelected: true }, { name: 'three', isSelected: true } ] console.log(initialArray === changedArray); // false

注意:此解決方案不允許您在不使用擴展運算符的情況下取消引用嵌套在第一層之外的任何對象。

可以在此處找到有關spread運算符的更多信息。

 var targetArray=JSON.parse(JSON.stringify(souceArray));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM