1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
|
---
title: Array.prototype.slice()
slug: Web/JavaScript/Reference/Global_Objects/Array/slice
tags:
- Array
- JavaScript
- Method
- Prototype
- Reference
translation_of: Web/JavaScript/Reference/Global_Objects/Array/slice
---
<div>{{JSRef}}</div>
<p><code><strong>slice()</strong></code> 方法會回傳一個新陣列物件,為原陣列選擇之 <code>begin</code> 至 <code>end</code>(不含 <code>end</code>)部分的淺拷貝(shallow copy)。而原本的陣列將不會被修改。</p>
<div>{{EmbedInteractiveExample("pages/js/array-slice.html")}}</div>
<p class="hidden">The source for this interactive demo is stored in a GitHub repository. If you'd like to contribute to the interactive demo project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p>
<h2 id="語法">語法</h2>
<pre class="syntaxbox notranslate"><var>arr</var>.slice(<em>[</em><var>begin[</var>, <var>end]]</var>)
</pre>
<h3 id="參數">參數</h3>
<dl>
<dt><code>begin</code> {{optional_inline}}</dt>
<dd>自哪一個索引(起始為 0)開始提取拷貝。</dd>
<dd>可使用負數索引,表示由陣列的最末項開始提取。<code>slice(-2)</code> 代表拷貝陣列中的最後兩個元素。</dd>
<dd>假如 <code>begin</code> 為 undefined,則 <code>slice</code> 會從索引 <code>0</code> 開始提取。</dd>
<dt><code>end</code> {{optional_inline}}</dt>
<dd>至哪一個索引(起始為 0)<em>之前</em>停止提取。<code>slice</code> 提取但不包含至索引 <code>end</code>。</dd>
<dd>舉例來說,<code>slice(1,4)</code> 提取了陣列中第二個元素至第四個元素前為止(元素索引 1、2 以及 3)來拷貝。</dd>
<dd>可使用負數索引,表示由陣列的最末項開始提取。<code>slice(2,-1)</code> 代表拷貝陣列中第三個元素至倒數第二個元素。</dd>
<dd>若省略了 <code>end</code>,則 <code>slice</code> 會提取至陣列的最後一個元素(<code>arr.length</code>)。</dd>
<dd>假如 <code>end</code> 大於陣列的長度,<code>slice</code> 會提取至陣列的最後一個元素(<code>arr.length</code>)。</dd>
</dl>
<h3 id="回傳值">回傳值</h3>
<p>一個包含提取之元素的新陣列。</p>
<h2 id="說明">說明</h2>
<p><code>slice</code> 不會修改原本的陣列,而是回傳由原本的陣列淺層複製的元素。原始陣列的元素會按照下列規則拷貝:</p>
<ul>
<li>如果該元素是個對象引用(不是實際的對象),<code>slice</code> 會拷貝這個對象引用到新的陣列內。兩個對象引用都引用了同一個對象。如果被引用的對象發生改變,則新的和原來的陣列中的這個元素也會發生改變。</li>
<li>對於字串、數字、布林來說 (不是 <a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/String"><code>String</code></a>、<a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Number"><code>Number</code></a> 或者 <a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Boolean"><code>Boolean</code></a> 對象), <code>slice</code> 會拷貝這些值到新的陣列內。在別的陣列內修改這些字串、數字或是布林,將不會影響另一個陣列。</li>
</ul>
<p>如果添加了新的元素到另一個陣列內,則另一個不會受到影響。</p>
<h2 id="範例">範例</h2>
<h3 id="Return_a_portion_of_an_existing_array">Return a portion of an existing array</h3>
<pre class="brush: js notranslate">var fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];
var citrus = fruits.slice(1, 3);
// fruits contains ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango']
// citrus contains ['Orange','Lemon']
</pre>
<h3 id="Using_slice">Using <code>slice</code></h3>
<p>In the following example, <code>slice</code> creates a new array, <code>newCar</code>, from <code>myCar</code>. Both include a reference to the object <code>myHonda</code>. When the color of <code>myHonda</code> is changed to purple, both arrays reflect the change.</p>
<pre class="brush: js notranslate">// Using slice, create newCar from myCar.
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);
// Display the values of myCar, newCar, and the color of myHonda
// referenced from both arrays.
console.log('myCar = ' + JSON.stringify(myCar));
console.log('newCar = ' + JSON.stringify(newCar));
console.log('myCar[0].color = ' + myCar[0].color);
console.log('newCar[0].color = ' + newCar[0].color);
// Change the color of myHonda.
myHonda.color = 'purple';
console.log('The new color of my Honda is ' + myHonda.color);
// Display the color of myHonda referenced from both arrays.
console.log('myCar[0].color = ' + myCar[0].color);
console.log('newCar[0].color = ' + newCar[0].color);
</pre>
<p>This script writes:</p>
<pre class="brush: js notranslate">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
</pre>
<h2 id="類陣例(Array-like)物件">類陣例(Array-like)物件</h2>
<p><code>slice</code> method can also be called to convert Array-like objects / collections to a new Array. You just bind the method to the object. The {{jsxref("Functions/arguments", "arguments")}} inside a function is an example of an 'array-like object'.</p>
<pre class="brush: js notranslate">function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); // [1, 2, 3]
</pre>
<p>Binding can be done with the .<code>call</code> function of {{jsxref("Function.prototype")}} and it can also be reduced using <code>[].slice.call(arguments)</code> instead of <code>Array.prototype.slice.call</code>. Anyway, it can be simplified using {{jsxref("Function.prototype.bind", "bind")}}.</p>
<pre class="brush: js notranslate">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]
</pre>
<h2 id="Streamlining_cross-browser_behavior">Streamlining cross-browser behavior</h2>
<p>Although host objects (such as DOM objects) are not required by spec to follow the Mozilla behavior when converted by <code>Array.prototype.slice</code> and IE < 9 does not do so, versions of IE starting with version 9 do allow this. “Shimming” it can allow reliable cross-browser behavior. As long as other modern browsers continue to support this ability, as currently do IE, Mozilla, Chrome, Safari, and Opera, developers reading (DOM-supporting) slice code relying on this shim will not be misled by the semantics; they can safely rely on the semantics to provide the now apparently <em>de facto</em> standard behavior. (The shim also fixes IE to work with the second argument of <code>slice()</code> being an explicit {{jsxref("null")}}/{{jsxref("undefined")}} value as earlier versions of IE also did not allow but all modern browsers, including IE >= 9, now do.)</p>
<pre class="brush: js notranslate">/**
* 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 ES2015, 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 : 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;
};
}
}());
</pre>
<h2 id="規範">規範</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td>{{SpecName('ES3')}}</td>
<td>{{Spec2('ES3')}}</td>
<td>Initial definition. Implemented in JavaScript 1.2.</td>
</tr>
<tr>
<td>{{SpecName('ES5.1', '#sec-15.4.4.10', 'Array.prototype.slice')}}</td>
<td>{{Spec2('ES5.1')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('ES6', '#sec-array.prototype.slice', 'Array.prototype.slice')}}</td>
<td>{{Spec2('ES6')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-array.prototype.slice', 'Array.prototype.slice')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="瀏覽器相容性">瀏覽器相容性</h2>
<div>
<p>{{Compat("javascript.builtins.Array.slice")}}</p>
</div>
<h2 id="參見">參見</h2>
<ul>
<li>{{jsxref("Array.prototype.splice()")}}</li>
<li>{{jsxref("Function.prototype.call()")}}</li>
<li>{{jsxref("Function.prototype.bind()")}}</li>
</ul>
|