slice()
方法会浅复制(shallow copy)数组的一部分到一个新的数组,并返回这个新数组。
语法
arr.slice([begin[, end]])
参数
begin
- 从该索引处开始提取原数组中的元素(从0开始)。
- 如果该参数为负数,
则表示从原数组中的倒数第几个元素开始提取,
slice(-2)
表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。 - 如果省略
begin
,则slice
从索引 0 开始。
end
- 在该索引处结束提取原数组元素(从0开始)。
slice
会提取原数组中索引从begin
到end
的所有元素(包含begin,但不包含end)。 slice(1,4)
提取原数组中的第二个元素开始直到第四个元素的所有元素 (索引为 1, 2, 3的元素)。- 如果该参数为负数,
则它表示在原数组中的倒数第几个元素结束抽取
。slice(-2,-1)
表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。 - 如果
end
被省略,则slice
会一直提取到原数组末尾。
返回值
一个含有提取元素的新数组
描述
slice
不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。原数组的元素会按照下述规则拷贝:
- 如果该元素是个对象引用 (不是实际的对象),
slice
会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。
如果向两个数组任一中添加了新元素,则另一个不会受到影响。
示例
返回数组中的一部分
// Our good friend the citrus from fruits example var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"]; var citrus = fruits.slice(1, 3); // puts --> ["Orange","Lemon"]
使用 slice
在下例中, slice从
myCar中创建了一个新数组
newCar
.两个数组都包含了一个myHonda
对象的引用. 当myHonda
的color属性改变为purple, 则两个数组中的对应元素都会随之改变.
// 使用slice方法从myCar中创建一个newCar. var myHonda = { color: "red", wheels: 4, engine: { cylinders: 4, size: 2.2 } }; var myCar = [myHonda, 2, "cherry condition", "purchased 1997"]; var newCar = myCar.slice(0, 2); // 输出myCar, newCar,以及各自的myHonda对象引用的color属性. print("myCar = " + myCar.toSource()); print("newCar = " + newCar.toSource()); print("myCar[0].color = " + myCar[0].color); print("newCar[0].color = " + newCar[0].color); // 改变myHonda对象的color属性. myHonda.color = "purple"; print("The new color of my Honda is " + myHonda.color); //输出myCar, newCar中各自的myHonda对象引用的color属性. print("myCar[0].color = " + myCar[0].color); print("newCar[0].color = " + newCar[0].color);
上述代码输出:
myCar = [{color:"red", wheels:4, engine:{cylinders:4, size:2.2}}, 2, "cherry condition", "purchased 1997"] newCar = [{color:"red", wheels:4, engine:{cylinders:4, size:2.2}}, 2] myCar[0].color = red newCar[0].color = red The new color of my Honda is purple myCar[0].color = purple newCar[0].color = purple
类数组(Array-like)对象
slice
方法可以用来将一个类数组(Array-like)对象/集合转换成一个数组。你只需将该方法绑定到这个对象上。下述代码中 list 函数中的 arguments
就是一个类数组对象。
function list() { return Array.prototype.slice.call(arguments); } var list1 = list(1, 2, 3); // [1, 2, 3]
除了使用 Array.prototype.slice.call(
arguments
)
,你也可以简单的使用 [].slice.call(arguments)
来代替。另外,你可以使用 bind
来简化该过程。
var unboundSlice = Array.prototype.slice; var slice = Function.prototype.call.bind(unboundSlice); function list() { return slice(arguments); } var list1 = list(1, 2, 3); // [1, 2, 3]
更可靠地跨浏览器
根据规范,使用 Array.prototype.slice 转换宿主对象(如 DOM 对象)时不必遵循 Mozilla 的默认行为,即可以转化任何符合条件的伪数组宿主对象为数组,IE < 9 没有遵循,而 IE9 + 遵循这个行为,但是稍加改造可以使其在跨浏览器使用时更可靠。只要其他现代浏览器继续支持该行为,目前 IE 9+、FireFox、Chrome、Safari 以及 Opera 都支持,开发者在使用下面代码时遍历 DOM 时就不会被该方法的字面意义误导,即 IE < 9 不能转化 DOM Collections。开发者可以安全地根据语义知道该方法的实际上的标准行为。(下面的代码还修正了 IE 中 slice()
方法第二个参数不允许为显式的 null
/undefined
值的问题,其他现代浏览器,包括IE9+都允许)。
/** * Shim for "fixing" IE's lack of support (IE < 9) for applying slice * on host objects like NamedNodeMap, NodeList, and HTMLCollection * (technically, since host objects have been implementation-dependent, * at least before ES6, IE hasn't needed to work this way). * Also works on strings, fixes IE < 9 to allow an explicit undefined * for the 2nd argument (as in Firefox), and prevents errors when * called on other DOM objects. */ (function () { 'use strict'; var _slice = Array.prototype.slice; try { // Can't be used with DOM elements in IE < 9 _slice.call(document.documentElement); } catch (e) { // Fails in IE < 9 // 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: len + start; // Handle negative value for "end" var upTo = (end) ? end : 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; }; } }());
规范
Specification | Status | Comment |
---|---|---|
ECMAScript 3rd Edition (ECMA-262) | Standard | Initial definition. Implemented in JavaScript 1.2 |
ECMAScript 5.1 (ECMA-262) Array.prototype.slice |
Standard | |
ECMAScript 2015 (6th Edition, ECMA-262) Array.prototype.slice |
Standard | |
ECMAScript 2017 Draft (ECMA-262) Array.prototype.slice |
Draft |
浏览器兼容性
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | 1.0 | 1.0 (1.7 or earlier) | (Yes) | (Yes) | (Yes) |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |