如何在不丢失引用的情况下替换数组元素?

8
如何替换数组中的所有元素而不丢失引用?
var arr = [1, 2, 3];
var b = arr;
b == arr; // true
magic(arr, [4, 5, 6]);
b == arr; // should return true

一种做法是通过弹出和推入来实现。是否有更简洁的方法?

5个回答

9
您可以将旧值拼接并追加新值。

function magic(reference, array) {
    [].splice.apply(reference, [0, reference.length].concat(array));
}

var arr = [1, 2, 3],
    b = arr;

console.log(b === arr); // true
magic(arr, [4, 5, 6]);
console.log(b === arr); // should return true

console.log(arr);

另一种方法是使用 Object.assign。如果数组比原始数组小,需要设置数组的长度。

function magic(reference, array) {
    Object.assign(reference, array, { length: array.length });
}

var arr = [1, 2, 3],
    b = arr;

console.log(b === arr); // true
magic(arr, [4, 5, 6, 7]);
console.log(b === arr); // should return true

console.log(arr);


1
没有什么可质疑的,这只是让我微笑的事情。 - Patrick Roberts
@NinaScholz 这似乎是很多工作,只是为了将一个数组中的值复制到另一个数组中。 - user663031
1
@NinaScholz:[].apply相对于reference.splice(0, reference.length, ...array)有什么优势?只是为了兼容ES5吗? - Scott Sauyet
1
@ScottSauyet,这只是与ES5的兼容性问题。使用ES6,您可以使用扩展语法或上述提到的Object.assign。实际上,该请求需要一个变异器函数。 - Nina Scholz
@torazaburo,在保留引用的同时仍需要一些操作,可以使用length和push、splice或Object.assign。 - Nina Scholz

2

关键在于神奇的地方可能是:

arr.splice(0, arr.length, 4, 5, 6);

var arr = [1, 2, 3];
var b = arr;
b == arr; // true
arr.splice(0, arr.length, 4, 5, 6);
console.log(b);
console.log(arr);
console.log(arr === b);
.as-console-wrapper { max-height: 100% !important; top: 0; }

如果您已经将替换数组存储在变量中(假设为repl = [4, 5, 6]),那么请使用rest parameters语法:

arr.splice(0, arr.length, ...repl);

var arr = [1, 2, 3];
var b = arr;
var repl = [4, 5, 6];
b == arr; // true

arr.splice(0, arr.length, ...repl);
console.log(b);
console.log(arr);
console.log(arr === b);
.as-console-wrapper { max-height: 100% !important; top: 0; }


1
这是一种方法:

var arr = [1, 2, 3];
var b = arr;
console.log(`b == arr, b
`, b == arr, b.join());
var c = magic(arr, [4, 5, 6]);
console.log(`b == arr, b
`, b == arr, b.join());
console.log(`c == arr, c
`, c == arr, c.join());

function magic(to, from) {
  // remove elements from existing array
  var old = to.splice(0);
  
  for (var i = 0; i < from.length; i++) {
    to[i] = from[i];
  }
  
  return old;
}

这个实现返回一个原始数组中旧元素的副本。

0

将新的值复制到旧的值上。

function magic(arr, newvals) {
  for (let i = 0; i < newvals.length; i++) arr[i] = newvals[i];
  arr.length = newvals.length;
}

0
function replaceArrValues(arrRef, newValues)
{
  arrRef.length = 0; // clear the array without losing reference
  newValues.forEach(x => arrRef.push(x));
}

这个只有代码的答案可以通过添加一些书面解释来改进。特别是:这与其他人提供的“splice”技术相比如何? - Wyck
虽然这段代码片段可能是解决方案,但包括解释真的有助于提高您的帖子质量。请记住,您正在回答未来读者的问题,而这些人可能不知道您的代码建议的原因。 - nircraft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接