js Array.slice的8种不同用法示例


Posted in Javascript onJuly 10, 2019

前言

JS数组slice方法是JS语言中最强大、最常用的内建函数之一。

随着React和其他面向功能的JavaScript实践的兴起,它变得越来越重要,原因有两个:

  • 函数式编程,尤其是高阶函数,与数据列表密切配合
  • 函数式编程需要纯函数,即不会产生副作用或修改输入数据的函数

JavaScript 数组slice方法符合这两个标准。

slice方法可以在不修改原始列表的情况下创建列表子集的浅拷贝。因此,它为编写函数式 JS 提供了一个关键的构建块。

在这篇文章中,我们将通过实例来掌握slice方法,探索它的8种不同用法。

注意:slice 方法不要与splice方法混淆,splice方法会修改原始数组。

slice 工作原理

在深入研究一些更高级的用法之前,让我们看一下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的核心功能。

用法1:简单的复制

const arr2 = arr.slice

没有任何参数的slice执行一个简单的浅拷贝。当前,主流的用法还是使用展开运算符合来实现,但是如果在旧的代码库中,或者没有使用babel的构建步骤,可能仍然希望使用slice。

用法2:获取从 N 开始的子数组

使用slice方法最简单的方法就是原始数组从N开始抽取的所有元素。

一种情况是希望弹出数组的第一个元素并使用它,返回剩余的数组,但希望在不修改原始数组的情况下执行此操作。

function useone (arr) {
 const usedItem = arr[0]
 return arr.slice(1)
}

用法3:获取从末尾 N 开始的子数组

slice的另一种使用方法是获取数组的末尾,利用的是负索引从末尾开始计数。

这种负索引使删除任意数量的元素变得超级简单。例如,如果你只想抓取3个

const last3 = arr.slice(-3)

用法4:获取数组的前n个

获取数组的前面的数,我们需要使用第二个参数:end。

当有两个参数时,slice方法返回一个从begin开始但不包括end的集合。

由于JavaScript数组是从0开始的(索引从0开始),这使得获取前N个元素变得非常简单:

const first4 = arr.slice(0, 4)

用法5:获取数组中某段子数组

如果我们想要使用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)

在这特定的场合中会很有用处。

用法6:将类似数组的对象转换为数组

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 ]

用法7:将任意长度多余的参数强制转换为数组

有时希望接受函数的多余参数,组成一个数组。

较新版本的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]

用法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));
 }
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
几行代码轻松搞定jquery实现flash8类似的连接效果
May 03 Javascript
jquery遍历筛选数组的几种方法和遍历解析json对象
Dec 13 Javascript
JavaScript从数组中删除指定值元素的方法
Mar 18 Javascript
js显示当前日期时间和星期几
Oct 22 Javascript
javascript数组克隆简单实现方法
Dec 16 Javascript
AngularJS基础 ng-selected 指令简单示例
Aug 03 Javascript
node.js中fs.stat与fs.fstat的区别详解
Jun 01 Javascript
label+input实现按钮开关切换效果的实例
Aug 16 Javascript
用js简单提供增删改查接口
May 12 Javascript
在Vue中使用icon 字体图标的方法
Jun 14 Javascript
新手如何快速理解js异步编程
Jun 24 Javascript
详解Node.js如何处理ES6模块
May 15 Javascript
vue-router二级导航切换路由及高亮显示的实现方法
Jul 10 #Javascript
Vue编程式跳转的实例代码详解
Jul 10 #Javascript
微信小程序在ios下Echarts图表不能滑动的问题解决
Jul 10 #Javascript
Vue事件修饰符native、self示例详解
Jul 09 #Javascript
如何自定义微信小程序tabbar上边框的颜色
Jul 09 #Javascript
微信小程序wx.request拦截器使用详解
Jul 09 #Javascript
javascript实现图片轮播代码
Jul 09 #Javascript
You might like
PHP5.0对象模型探索之抽象方法和抽象类
2006/09/05 PHP
无数据库的详细域名查询程序PHP版(2)
2006/10/09 PHP
Symfony模板的快捷变量用法实例
2016/03/17 PHP
PHP MSSQL 分页实例
2016/04/13 PHP
PHP读取目录树的实现方法分析
2019/03/22 PHP
laravel框架创建授权策略实例分析
2019/11/22 PHP
Wordpress ThickBox 添加“查看原图”效果代码
2010/12/11 Javascript
JS实现div内部的文字或图片自动循环滚动代码
2013/04/19 Javascript
嵌入式iframe子页面与父页面js通信的方法
2015/01/20 Javascript
jQuery提示插件alertify使用指南
2015/04/21 Javascript
js插件设置innerHTML时在IE8下提示“未知运行时错误”解决方法
2015/04/25 Javascript
JS实现图片高亮展示效果实例
2015/11/24 Javascript
JavaScript常用字符串与数组扩展函数小结
2016/04/24 Javascript
基于BootStrap的Metronic框架实现页面链接收藏夹功能按钮移动收藏记录(使用Sortable进行拖动排序)
2016/08/29 Javascript
jQuery Collapse1.1.0折叠插件简单使用
2017/08/28 jQuery
vue-music关于Player播放器组件详解
2017/11/28 Javascript
JS实现利用两个队列表示一个栈的方法
2017/12/13 Javascript
微信小程序实现可拖动悬浮图标(包括按钮角标的实现)
2020/12/29 Javascript
[01:02:03]2014 DOTA2华西杯精英邀请赛 5 24 NewBee VS VG
2014/05/26 DOTA
[44:58]2018DOTA2亚洲邀请赛 4.5 淘汰赛 LGD vs Liquid 第二场
2018/04/06 DOTA
Python写的PHPMyAdmin暴力破解工具代码
2014/08/06 Python
python魔法方法-属性访问控制详解
2016/07/25 Python
python处理Excel xlrd的简单使用
2017/09/12 Python
解决pandas read_csv 读取中文列标题文件报错的问题
2018/06/15 Python
用python给自己做一款小说阅读器过程详解
2019/07/11 Python
Django 创建/删除用户的示例代码
2019/07/24 Python
python tkinter实现屏保程序
2019/07/30 Python
python3 selenium自动化 frame表单嵌套的切换方法
2019/08/23 Python
Python列表嵌套常见坑点及解决方案
2020/09/30 Python
CSS3 transforms应用于背景图像的解决方法
2019/04/16 HTML / CSS
Currentbody德国站:健康与美容技术专家
2020/04/05 全球购物
校三好学生主要事迹
2014/01/11 职场文书
美国留学经济担保书
2014/05/20 职场文书
药品销售员2015年终工作总结
2015/10/22 职场文书
三严三实·严以律己心得体会
2016/01/13 职场文书
关于React Native 无法链接模拟器的问题
2021/06/21 Javascript