aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/reference/global_objects/array/slice/index.html
blob: eb68df4907626913668066e097eb95216d58e882 (plain)
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
243
244
245
246
247
248
249
250
251
252
253
---
title: Array.prototype.slice()
slug: Web/JavaScript/Reference/Global_Objects/Array/slice
tags:
  - Array
  - JavaScript
  - Prototype
  - 原型
  - 数组
  - 方法
translation_of: Web/JavaScript/Reference/Global_Objects/Array/slice
---
<div>{{JSRef}}</div>

<p><code><strong title="切片">slice()</strong></code> 方法返回一个新的数组对象,这一对象是一个由 <code>begin</code><code>end</code> 决定的原数组的<strong>浅拷贝</strong>(包括 <code>begin</code>,不包括<code>end</code>)。原始数组不会被改变。</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([<var>begin</var>[, <var>end</var>]])</pre>

<h2 id="参数">参数</h2>

<dl>
 <dt><code>begin</code> {{optional_inline}}</dt>
 <dd>提取起始处的索引(从 <code>0</code> 开始),从该索引开始提取原数组元素。</dd>
 <dd>如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,<code>slice(-2)</code> 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。</dd>
 <dd>如果省略 <code>begin</code>,则 <code>slice</code> 从索引 <code>0</code> 开始。</dd>
 <dd>如果 <code>begin</code> 超出原数组的索引范围,则会返回空数组。</dd>
</dl>

<dl>
 <dt><code>end</code> {{optional_inline}}</dt>
 <dd>提取终止处的索引(从 <code>0</code> 开始),在该索引处结束提取原数组元素。<code>slice</code> 会提取原数组中索引从 <code>begin</code> 到 <code>end</code> 的所有元素(包含 <code>begin</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> 会一直提取到原数组末尾。</dd>
 <dd>如果 <code>end</code> 大于数组的长度,<code>slice</code> 也会一直提取到原数组末尾。</dd>
</dl>

<h3 id="返回值">返回值</h3>

<p>一个含有被提取元素的新数组。</p>

<h2 id="描述">描述</h2>

<p><code>slice</code> 不会修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。原数组的元素会按照下述规则拷贝:</p>

<ul>
 <li>如果该元素是个对象引用 (不是实际的对象),<code>slice</code> 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。</li>
</ul>

<ul>
 <li>对于字符串、数字及布尔值来说(不是 {{jsxref("Global_Objects/String", "String")}}{{jsxref("Global_Objects/Number", "Number")}} 或者 {{jsxref("Boolean")}} 对象),<code>slice</code> 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。</li>
</ul>

<p>如果向两个数组任一中添加了新元素,则另一个不会受到影响。</p>

<h2 id="Examples" name="Examples">示例</h2>

<h3 id="返回现有数组的一部分">返回现有数组的一部分</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>

<div class="standardNoteBlock">
<p class="syntaxbox"><strong>译者注:citrus</strong> <em>[n.]</em> 柑橘类果实</p>
</div>

<h3 id="使用_slice">使用 <code>slice</code></h3>

<p>在下例中, <code>slice</code><code>myCar</code> 中创建了一个新数组<code>newCar</code>。两个数组都包含了一个 <code>myHonda</code> 对象的引用。当 <code>myHonda</code><code>color</code> 属性改变为 <code>purple</code>,则两个数组中的对应元素都会随之改变。</p>

<pre class="brush: js notranslate">// 使用 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 属性。
console.log(' myCar = ' + JSON.stringify(myCar));
console.log('newCar = ' + JSON.stringify(newCar));
console.log(' myCar[0].color = ' + JSON.stringify(myCar[0].color));
console.log('newCar[0].color = ' + JSON.stringify(newCar[0].color));

// 改变 myHonda 对象的 color 属性.
myHonda.color = 'purple';
console.log('The new color of my Honda is ' + myHonda.color);

//输出 myCar、newCar 中各自的 myHonda 对象引用的 color 属性。
console.log(' myCar[0].color = ' + myCar[0].color);
console.log('newCar[0].color = ' + newCar[0].color);
</pre>

<p>上述代码输出:</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" name="Array-like">类数组(Array-like)对象</h2>

<p><code>slice</code> 方法可以用来将一个类数组(Array-like)对象/集合转换成一个新数组。你只需将该方法绑定到这个对象上。 一个函数中的  {{jsxref("Functions/arguments", "arguments")}} 就是一个类数组对象的例子。</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>除了使用 <code>Array.prototype.slice.call(</code><code>arguments</code><code>)</code>,你也可以简单的使用 <code>[].slice.call(arguments)</code> 来代替。另外,你可以使用 <code>bind</code> 来简化该过程。</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="精简跨浏览器行为">精简跨浏览器行为</h2>

<p>根据规范,使用 <code>Array.prototype.slice</code> 转换宿主对象(如 DOM 对象)时,不必遵循 Mozilla 的默认行为,即可以转化任何符合条件的伪数组宿主对象为数组,IE &lt; 9 没有遵循,而 IE9 + 遵循这个行为,但是稍加改造可以使其在跨浏览器使用时更可靠。只要其他现代浏览器继续支持该行为,目前 IE 9+、FireFox、Chrome、Safari 以及 Opera 都支持,开发者在使用下面代码时遍历 DOM 时就不会被该方法的字面意义误导,即 IE &lt; 9 不能转化 DOM Collections。开发者可以安全地根据语义知道该方法的实际上的标准行为。(下面的代码还修正了 IE 中 <code>slice()</code> 方法第二个参数不允许为显式的 {{jsxref("Global_Objects/null", "null")}}/{{jsxref("Global_Objects/undefined", "undefined")}} 值的问题,其他现代浏览器,包括 IE9+ 都允许)。</p>

<pre class="brush: js notranslate">/**
 * Shim for "fixing" IE's lack of support (IE &lt; 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 &lt; 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 &lt; 9
    _slice.call(document.documentElement);
  } catch (e) { // Fails in IE &lt; 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 &lt; 9)
    Array.prototype.slice = function(begin, end) {
      // IE &lt; 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 &gt;= 0) ? start : Math.max(0, len + start);

      // Handle negative value for "end"
      var upTo = (typeof end == 'number') ? Math.min(end, len) : len;
      if (end &lt; 0) {
        upTo = len + end;
      }

      // Actual expected size of the slice
      size = upTo - start;

      if (size &gt; 0) {
        cloned = new Array(size);
        if (this.charAt) {
          for (i = 0; i &lt; size; i++) {
            cloned[i] = this.charAt(start + i);
          }
        } else {
          for (i = 0; i &lt; size; i++) {
            cloned[i] = this[start + i];
          }
        }
      }

      return cloned;
    };
  }
}());
</pre>

<h2 id="规范" style="margin-bottom: 20px; line-height: 30px;">规范</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">规范</th>
   <th scope="col">状态</th>
   <th scope="col">备注</th>
  </tr>
  <tr>
   <td>{{SpecName('ES3')}}</td>
   <td>{{Spec2('ES3')}}</td>
   <td>Initial definition.<br>
    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="浏览器兼容性" style="margin-bottom: 20px; line-height: 30px;">浏览器兼容性</h2>

<div>


<p>{{Compat("javascript.builtins.Array.slice")}}</p>
</div>

<h2 id="See_also" name="See_also" style="margin-bottom: 20px; line-height: 30px;">相关链接</h2>

<ul>
 <li>{{jsxref("Array.prototype.splice()")}}</li>
 <li>{{jsxref("Function.prototype.call()")}}</li>
 <li>{{jsxref("Function.prototype.bind()")}}</li>
</ul>