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 functionat test (repl:2:18)at repl:1:1at 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 fnreturn function() {var remainingArgs = Array.prototype.slice.call(arguments);return fn.apply(this, args.concat(remainingArgs));}
}

js中 slice 用法用法全解析相关推荐

  1. slice在php里面什么意思,js中slice()使用方法

    本文主要和大家分享js中slice()使用方法,slice()通过索引位置获取新的数组,该方法不会修改原数组,只是返回一个新的子数组. 用法:arrayObj.slice(start,end)arra ...

  2. JS中的new操作符原理解析

    JS中的new操作符原理解析 new操作符做了什么 参考 推荐阅读 你越是认真生活,你的生活就会越美好--弗兰克·劳埃德·莱特 <人生果实>经典语录 new操作符做了什么 var Pers ...

  3. js变量提升_学习笔记:JS中的作用域和预解析

    知识总结:谢静贤.汤昊 在javascript中作用域是非常重要的,本文将会说明作用域以及我们在工作,以及面试中的一些面试题,如果有不足的地方希望大家可以评论指出来,自己一定会及时的改正错误,避免大家 ...

  4. js中prototype用法(转)

    JavaScript能够实现的面向对象的特征有: ·公有属性(public field) ·公有方法(public Method) ·私有属性(private field) ·私有方法(private ...

  5. js中every用法_JS中every()和some()的用法

    every()与some()方法都是JS中数组的迭代方法. every()是对数组中每一项运行给定函数,如果该函数对每一项返回true,则返回true. some()是对数组中每一项运行给定函数,如果 ...

  6. Js中Promise用法

    promise是用来解决Js中的异步问题的.基本结构如下: function a() {return new Promise((resolve, reject) => {//dosomethin ...

  7. js中slice、splice用法与区别

    1.slice(start,end)(参数可选) slice() 方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象.原始数组不会被修改. var a = ['a', 'b ...

  8. js中 slice , splice , split 的用法记录

    1.slice不改变原数组 a.slice(1,5)删除数组从序号为1开始到序号为5(不包含序号为5)之间的元素 2.splice改变原数组 a.splice(1,3) 删除数组从序号为1的元素开始, ...

  9. js中typeof用法详细介绍

    本文章来介绍在js使用中的一个函数typeof用法, typeof 运算符把类型信息当作字符串返回,包括有大家常有变量类型. typeof 运算符把类型信息当作字符串返回.typeof 返回值有六种可 ...

最新文章

  1. Vue.js 学习笔记 第5章 内置指令
  2. 双击SDK Manager.exe和AVD Manager.exe时,弹出提示:failed to execute tools\android.bat解决办法
  3. 现在是2016-09-23,查询2个月后的月份和入职的月份相同的数据
  4. jeecg json返回值显示失败or成功 j.setSuccess(false/*true*/)
  5. 磁盘I/O高居不下,通过什么来查看占用I/O的进程?
  6. 【Python实例第8讲】模型复杂度影响
  7. 2020暨大计算机考研失败经验总结
  8. 固态硬盘(samsung SSD 850 pro)相关问题
  9. Leetcode题目解答汇总
  10. c#chart控件代码详解
  11. Tensorflow - 训练中出现 Nan 值
  12. html班级管理,谈小学班级管理
  13. Rasa课程、Rasa培训、Rasa面试、Rasa实战系列之 Response Selection
  14. myeclipse7.5注册码
  15. 机器学习系列笔记一:Introduction
  16. 防止进程被任务管理器关掉的办法
  17. 计算机网络期末考试重点
  18. 质量人想获取领导赞赏,首先要划出漂亮的鱼骨图!
  19. 将一个字符串反转后并输出,代码如下:
  20. 如何添加在线QQ咨询?

热门文章

  1. 将GUI添加到Windows Server Core和Hyper-V Core
  2. chrome84版本解决加载flash插件问题
  3. Andorid FFMPEG播放SMB协议问题(1)
  4. OHDSI 相关内容 1
  5. chmod 命令用法
  6. 论坛介绍 | COSCon'22 开源教育(E)
  7. 打造Material Design风格的TabBar
  8. python 无头模式_selenium 无头模式获取日志performance出错
  9. python win32com + VBA宏 操作Excel,清除Excel中的公式
  10. react中的context,provider使用步骤