使用delete
操作符和使用Array.splice
方法在数组元素上的区别是什么?
例如:
myArray = ['a', 'b', 'c', 'd'];
delete myArray[1];
// or
myArray.splice (1, 1);
如果我可以像操作对象一样删除数组元素,那为什么还需要splice方法呢?
使用delete
操作符和使用Array.splice
方法在数组元素上的区别是什么?
例如:
myArray = ['a', 'b', 'c', 'd'];
delete myArray[1];
// or
myArray.splice (1, 1);
如果我可以像操作对象一样删除数组元素,那为什么还需要splice方法呢?
var my_array = [1,2,3,4,5,6];
delete my_array[4];
console.log(my_array.filter(function(a){return typeof a !== 'undefined';})); // [1,2,3,4,6]
slice
更直观(尽管可能不太高效)。 - jethrofunction reindexArray( array )
{
var result = [];
for( var key in array )
result.push( array[key] );
return result;
};
reindexArray : function( array )
{
var index = 0; // The index where the element should be
for( var key in array ) // Iterate the array
{
if( parseInt( key ) !== index ) // If the element is out of sequence
{
array[index] = array[key]; // Move it to the correct, earlier position in the array
++index; // Update the index
}
}
array.splice( index ); // Remove any remaining elements (These will be duplicates of earlier items)
},
> var arr = ["a","b","c","d"];
> delete arr[2]
true
> arr
[ 'a', 'b', , 'd', 'e' ]
这里有一个使用 slice() 函数按索引从数组中删除元素的方法,它将数组作为第一个参数,要删除的成员的索引作为第二个参数。正如您所看到的,它实际上删除了数组的成员,并使数组长度减少了1。
function(arr,arrIndex){
return arr.slice(0,arrIndex).concat(arr.slice(arrIndex + 1));
}
> var arr = ["a","b","c","d"]
> arr
[ 'a', 'b', 'c', 'd' ]
> arr.length
4
> var arrayRemoveIndex = require("./lib/array_remove_index");
> var newArray = arrayRemoveIndex(arr,arr.indexOf('c'))
> newArray
[ 'a', 'b', 'd' ] // c ya later
> newArray.length
3
已经有许多有关功能差异的好答案了 - 所以在这里我想集中讨论性能。今天(2020.06.25),我对Chrome 83.0、Safari 13.1和Firefox 77.0进行了测试,包括问题中提到的解决方案以及选择的答案。
splice
(B) solution is fast for small and big arraysdelete
(A) solution is fastest for big and medium fast for small arraysfilter
(E) solution is fastest on Chrome and Firefox for small arrays (but slowest on Safari, and slow for big arrays)function C(arr, idx) {
var rest = arr.slice(idx + 1 || arr.length);
arr.length = idx < 0 ? arr.length + idx : idx;
arr.push.apply(arr, rest);
return arr;
}
// Crash test
let arr = [...'abcdefghij'.repeat(100000)]; // 1M elements
try {
C(arr,1)
} catch(e) {console.error(e.message)}
function A(arr, idx) {
delete arr[idx];
return arr;
}
function B(arr, idx) {
arr.splice(idx,1);
return arr;
}
function C(arr, idx) {
var rest = arr.slice(idx + 1 || arr.length);
arr.length = idx < 0 ? arr.length + idx : idx;
arr.push.apply(arr, rest);
return arr;
}
function D(arr,idx){
return arr.slice(0,idx).concat(arr.slice(idx + 1));
}
function E(arr,idx) {
return arr.filter((a,i) => i !== idx);
}
myArray = ['a', 'b', 'c', 'd'];
[A,B,C,D,E].map(f => console.log(`${f.name} ${JSON.stringify(f([...myArray],1))}`));
This snippet only presents used solutions
Chrome的示例结果
myArray = myArray.filter(function(item){
return item.anProperty != whoShouldBeDeleted
});
delete
或 slice
更好。 - Juneyoung Ohsplice
是专门针对数组的,当用于删除时,会从数组中移除条目,并将所有先前的条目上移以填补空缺。(它也可以用于插入条目,或同时进行插入和删除。)splice
将改变数组的 length
(假设它不是一个无操作调用:theArray.splice(x, 0)
)。
delete
并不是只适用于数组,它被设计用于对象:它会从你使用的对象中删除一个属性(键值对)。它之所以适用于数组,是因为在JavaScript中,标准(例如非类型化)数组根本不是数组*,它们是带有特殊处理某些属性的对象,例如那些名为“数组索引”的属性(这些属性被定义为字符串名称“...其中数值 i 在范围+0 ≤ i < 2^32-1
内”)和length
。当您使用delete
删除数组条目时,它只会删除该条目;它不会移动其后面的其他条目来填补空缺,因此数组变得“稀疏”(完全丢失了一些条目)。它对length
没有影响。delete
会“将条目设置为undefined
”。这是不正确的。它会完全删除该条目(属性),留下一个空隙。console.log("Using `splice`:");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length); // 5
a.splice(0, 1);
console.log(a.length); // 4
console.log(a[0]); // "b"
console.log("Using `delete`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length); // 5
delete a[0];
console.log(a.length); // still 5
console.log(a[0]); // undefined
console.log("0" in a); // false
console.log(a.hasOwnProperty(0)); // false
console.log("Setting to `undefined`");
var a = ["a", "b", "c", "d", "e"];
console.log(a.length); // 5
a[0] = undefined;
console.log(a.length); // still 5
console.log(a[0]); // undefined
console.log("0" in a); // true
console.log(a.hasOwnProperty(0)); // true
* (这是我的不起眼的小博客上的一篇文章)
我有两种方法。
简单的方法:
arr = arr.splice(index,1)
第二个:
arr = arr.filter((v,i)=>i!==index)
arr = arr.filter((v,i)=>v!==value)
其他人已经正确地将delete
与splice
进行了比较。
另一个有趣的比较是delete
与undefined
之间的区别:被删除的数组项使用的内存比只设置为undefined
的数组项少;
例如,这段代码将无法完成:
let y = 1;
let ary = [];
console.log("Fatal Error Coming Soon");
while (y < 4294967295)
{
ary.push(y);
ary[y] = undefined;
y += 1;
}
console(ary.length);
它产生了这个错误:
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.
正如您所看到的, undefined
实际上占用了堆内存。
然而,如果您也删除
ary-item(而不仅仅将其设置为 undefined
),代码将慢慢完成:
let x = 1;
let ary = [];
console.log("This will take a while, but it will eventually finish successfully.");
while (x < 4294967295)
{
ary.push(x);
ary[x] = undefined;
delete ary[x];
x += 1;
}
console.log(`Success, array-length: ${ary.length}.`);
这些是极端的例子,但它们强调了一个关于 delete
的观点,我没有在任何地方看到过提到。
function remove_array_value(array, value) {
var index = array.indexOf(value);
if (index >= 0) {
array.splice(index, 1);
reindex_array(array);
}
}
function reindex_array(array) {
var result = [];
for (var key in array) {
result.push(array[key]);
}
return result;
}
例子:
var example_arr = ['apple', 'banana', 'lemon']; // length = 3
remove_array_value(example_arr, 'banana');
香蕉已被删除,数组长度为2。
目前有两种方法可以实现这个:
使用 splice()
arrayObject.splice(index, 1);
使用 delete
delete arrayObject[index];
但是我建议在数组对象中使用splice,在对象属性中使用delete,因为delete不会更新数组的长度。
.splice
,请参考这个问题:在JavaScript中从数组中删除元素。 - Rob Wdelete
和Array.prototype.splice
之间的区别。 - chharvey