译者:前端小智javascript
原文:codeburst.io/js-by-examp…html
阿里云最近在作活动,低至2折,有兴趣能够看看:promotion.aliyun.com/ntms/yunpar…前端
为了保证的可读性,本文采用意译而非直译。java
JS数组slice
方法是JS语言中最强大、最经常使用的内建函数之一。编程
随着React和其余面向功能的JavaScript实践的兴起,它变得愈来愈重要,缘由有两个:数组
函数式编程,尤为是高阶函数,与数据列表密切配合浏览器
函数式编程须要纯函数,即不会产生反作用或修改输入数据的函数babel
JavaScript 数组slice
方法符合这两个标准。app
slice
方法能够在不修改原始列表的状况下建立列表子集的浅拷贝。所以,它为编写函数式 JS 提供了一个关键的构建块。dom
在这篇文章中,咱们将经过实例来掌握slice
方法,探索它的8种不一样用法。
注意:
slice
方法不要与splice
方法混淆,splice
方法会修改原始数组。
在深刻研究一些更高级的用法以前,让咱们看一下slice
方法的基础知识。
如MDN文档,slice
是数组上的一个方法,它最多有两个参数:
arr.slice([begin[, end]])
复制代码
begin
从该索引处开始提取原数组中的元素,若是该参数为负数,则表示从原数组中的倒数第几个元素开始提取,slice(-2)
表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。 若是省略 begin
,则 slice
从索引 0 开始。
end
在该索引处结束提取原数组元素(从0开始)。slice
会提取原数组中索引从 begin
到 end
的全部元素(包含begin,但不包含end)。
slice(1,4)
提取原数组中的第二个元素开始直到第四个元素的全部元素 (索引为 1, 2, 3的元素)。
若是该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。 slice(-2,-1)
表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。
若是 end
被省略,则slice
会一直提取到原数组末尾。若是 end
大于数组长度,slice
也会一直提取到原数组末尾。
咱们的前4个例子突出slice
的核心功能。
const arr2 = arr.slice()
复制代码
没有任何参数的slice
执行一个简单的浅拷贝。当前,主流的用法仍是使用展开运算符合来实现,可是若是在旧的代码库中,或者没有使用babel
的构建步骤,可能仍然但愿使用slice
。
使用slice
方法最简单的方法就是原始数组从N
开始抽取的全部元素。
一种状况是但愿弹出数组的第一个元素并使用它,返回剩余的数组,但但愿在不修改原始数组的状况下执行此操做。
function useone (arr) {
const usedItem = arr[0]
return arr.slice(1)
}
复制代码
slice
的另外一种使用方法是获取数组的末尾,利用的是负索引
从末尾开始计数。
这种负索引使删除任意数量的元素变得超级简单。例如,若是你只想抓取3个
const last3 = arr.slice(-3)
复制代码
获取数组的前面的数,咱们须要使用第二个参数:end
。
当有两个参数时,slice
方法返回一个从begin
开始但不包括end
的集合。
因为JavaScript数组是从0
开始的(索引从0开始),这使得获取前N个元素变得很是简单:
const first4 = arr.slice(0, 4)
若是咱们想要使用slice
从任何索引开始获取数组的一段,该怎么办?
为此,咱们须要从 (begin, length)
转换为(begin, end)
。 计算逻辑很简单,咱们能够定义一个简单的函数来作到这一点:
function pullSegment(arr, begin, length) {
return arr.slice(begin, begin + length);
}
复制代码
JavaScript中,数组是一个特殊的对象,其property
名为正整数,且其length
属性会随着数组成员的增减而发生变化,同时又从Array
构造函数中继承了一些用于进行数组操做的方法。
而对于一个普通的对象来讲,若是它的全部property
名均为正整数,同时也有相应的length
属性,那么虽然该对象并非由Array
构造函数所建立的,它依然呈现出数组的行为,在这种状况下,这些对象被称为 “类数组对象” 。
slice
方法也可用于相似数组的对象。
一些相似数组包如arguments
(用于访问传递给函数的全部参数的关键字),NodeLists
(从返回节点列表的任何DOM API方法返回),甚至是使用数字索引并添加length
属性的原始对象。
要在相似数组的对象上使用slice
方法,须要直接从Array.prototype
引用它,以下所示:
Array.prototype.slice.call(arguments)
复制代码
在这特定的场合中会颇有用处。
slice
在相似数组的对象上的一个常见用途是将它们转换为实际数组。 例如:
const args = Array.prototype.slice.call(arguments);
你为何要这么作?为了使用数组方法。例如,想象一个像这样的函数
function addOne() {
return arguments.map(i => i+1);
}
复制代码
这看起来可行,但若是你试着去作,你就会获得错误:
> addOne(1, 2, 3)
TypeError: arguments.map is not a function
at test (repl:2:18)
at repl:1:1
at ContextifyScript.Script.runInThisContext (vm.js:44:33)
at REPLServer.defaultEval (repl.js:239:29)
at bound (domain.js:301:14)
at REPLServer.runBound [as eval] (domain.js:314:12)
at REPLServer.onLine (repl.js:440:10)
at emitOne (events.js:120:20)
at REPLServer.emit (events.js:210:7)
at REPLServer.Interface._onLine (readline.js:279:10)
复制代码
这是由于arguments
实际上不是数组,而是相似数组的对象。 可使用slice实现此功能,以下所示:
function addOne() {
return Array.prototype.slice.call(arguments).map(i => i+1)
}
复制代码
如今就能够获得了你所但愿的数据:
> addOne(1, 2, 3)
[ 2, 3, 4 ]
复制代码
有时但愿接受函数的多余参数,组成一个数组。
较新版本的JavaScript引入了所谓的Rest语法
来处理这个问题,可是若是为为了兼容旧浏览器,你可使用slice
作到这一点:
function myFunc(a, b) {
const extraArgs = Array.prototype.slice.call(arguments, 2);
}
复制代码
这容许使用任意数量的参数调用myFunc
, 例如:
myFunc(1, 2, 3, 4, 5, 6, 7, 8)
复制代码
在函数里面会获得a == 1
,b === 2
,extraArgs=== [3,4,5,6,7,8]
slice
在函数上下文中一个强大而常见的用法是替换数组中特定项的值。
从本质上讲,这很简单,只须要分配新值,可是在函数世界中,不能修改原始数组。
相反,能够将slice
与扩展运算符一块儿使用,以返回一个相同但对于要更新的索引的新数组:
function replaceIdx(arr, index, newVal) {
return [
...arr.slice(0, index),
newVal,
...arr.slice(index + 1)
]
}
复制代码
偏函数应用,英文是partial application
,也能够译做“局部应用”、“部分应用”、“偏应用”
函数式编程中的另外一种常见模式是所谓的偏函数应用:将函数预先应用于函数,而后返回一个新函数。
这种模式容许你组合函数,经过使用具备不一样预应用参数的相同核心函数来建立更大的可重用性。
虽然像Haskell这样的纯函数语言自己支持偏函数应用程序,可是在JavaScript中,咱们可使用slice
实现一个函数来实现它
var partial = function() {
const fn = arguments[0];
const args = Array.prototype.slice.call(arguments, 1);
// Return a function that calls fn
return function() {
var remainingArgs = Array.prototype.slice.call(arguments);
return fn.apply(this, args.concat(remainingArgs));
}
}
复制代码
我是小智,公众号「大迁世界」做者,对前端技术保持学习爱好者。我会常常分享本身所学所看的干货,在进阶的路上,共勉!
关注公众号,后台回复福利,便可看到福利,你懂的。