1.Array.prototype.slice()
slice() 方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对像,原始数组不会改变。
arrayObject.slice(start,end)
- start (可选,如果start不写则从0开始)从该索引处开始提取原数组中的元素。
如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,slice(-2)表示提取原数组的倒数第二个元素到最后一个元素(包含最后一个元素)。 - end(可选)在该索引处结束提取原数组元素(从0开始)。slice会提取原数组中索引从 begin 到 end 的所有元素(包含begin,但不包含end)。
*1.如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。 slice(-2,-1)表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。
2.如果 end 被省略,则slice 会一直提取到原数组末尾。
3.如果 end 大于数组长度,slice 也会一直提取到原数组末尾。*
原理:
(应该都能看懂)
// This will work for genuine arrays, array-like objects,
// NamedNodeMap (attributes, entities, notations),
// NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
// and will not fail on other DOM objects (as do DOM elements in IE < 9)
Array.prototype.slice = function(begin, end) {
// IE < 9 gets unhappy with an undefined end argument
end = (typeof end !== 'undefined') ? end : this.length;
// For native Array objects, we use the native slice function
if (Object.prototype.toString.call(this) === '[object Array]'){
return _slice.call(this, begin, end);
}
// For array like object we handle it ourselves.
var i, cloned = [],
size, len = this.length;
// Handle negative value for "begin"
var start = begin || 0;
start = (start >= 0) ? start : Math.max(0, len + start);
// Handle negative value for "end"
var upTo = (typeof end == 'number') ? Math.min(end, len) : len;
if (end < 0) {
upTo = len + end;
}
// Actual expected size of the slice
size = upTo - start;
if (size > 0) {
cloned = new Array(size);
if (this.charAt) {
for (i = 0; i < size; i++) {
cloned[i] = this.charAt(start + i);
}
} else {
for (i = 0; i < size; i++) {
cloned[i] = this[start + i];
}
}
}
return cloned;
};
还可以查看V8源码第587行:直达
2.Array.prototype.splice()
splice()方法通过删除现有元素和/或添加新元素来更改一个数组的内容。
原型:Array.prototype.splice (start, deleteCount, item1, item2, … )
- start
指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从1计数)。 - deleteCount (可选)
整数,表示要移除的数组元素的个数。如果 deleteCount 是 0,则不移除元素。这种情况下,至少应添加一个新元素。如果 deleteCount 大于start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 start 位)。 - item1, item2, …(可选)
要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素。
源码:
function ArraySplice(start, delete_count) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.splice");
var num_arguments = arguments.length;
var array = TO_OBJECT(this);
var len = TO_LENGTH(array.length);
var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
start_i);
var deleted_elements = ArraySpeciesCreate(array, del_count);
deleted_elements.length = del_count;
var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
if (del_count != num_elements_to_add && %object_is_sealed(array)) {
throw %make_type_error(kArrayFunctionsOnSealed);
} else if (del_count > 0 && %object_is_frozen(array)) {
throw %make_type_error(kArrayFunctionsOnFrozen);
}
var changed_elements = del_count;
if (num_elements_to_add != del_count) {
// If the slice needs to do a actually move elements after the insertion
// point, then include those in the estimate of changed elements.
changed_elements += len - start_i - del_count;
}
if (UseSparseVariant(array, len, IS_ARRAY(array), changed_elements)) {
%NormalizeElements(array);
if (IS_ARRAY(deleted_elements)) %NormalizeElements(deleted_elements);
SparseSlice(array, start_i, del_count, len, deleted_elements);
SparseMove(array, start_i, del_count, len, num_elements_to_add);
} else {
SimpleSlice(array, start_i, del_count, len, deleted_elements);
SimpleMove(array, start_i, del_count, len, num_elements_to_add);
}
// Insert the arguments into the resulting array in
// place of the deleted elements.
var i = start_i;
var arguments_index = 2;
var arguments_length = arguments.length;
while (arguments_index < arguments_length) {
array[i++] = arguments[arguments_index++];
}
array.length = len - del_count + num_elements_to_add;
// Return the deleted elements.
return deleted_elements;
}
还可以查看V8源码第660行:直达
或者开发文档:ECMA5.1文档
请注意
1.splice() 方法会直接对数组进行修改。slice() 不对数组进行修改,原数组不会改变。
2.splice() 返回值为被操作的值。slice() 以新的字符串返回被提取的部分。
3.
[14, 3, 77].slice(1, 2) // [3]
[14, 3, 77].splice(1, 2) // [3, 77]
4.splice先执行删除操作,删除指定个数的元素,然后再插入elements(元素或数组),他的每次删除都涉及大量元素的重新排列,而在插入元素时引入队列来管理。所以splice()的效率不高