Array.prototype.slice.call 将伪数组转成真数组的原理是什么?

2018-12-07 admin

好久没上SF,昨天上来看到一个问题,引起了我的兴趣。一番探索和研究后,有了此篇文章,也算是对该问题的解答。

let pretendArr = {0:0,1:1,2:2,length:3};
[].slice.call(pretendArr); //[0,1,2]

请看上面的例子 可能很多前端童鞋都很知道 Array.prototype.slice.call 可以用于将类数组对象转为数组,call 和 apply 的用法和作用网上一搜一大堆。 在这里主要是为了让 pretendArr 借用Array构造函数原型上的 slice 方法,并且改变 slice 方法里的 this 的指向。 所以这个问题其实不在于 call 或者 apply,关键在于 Array.prototype.slice 这个方法上。

slice这个方法是js原生方法,自然而然,我会想到去找找 es 的规范,看看这个方法是怎样定义,以及如何实现的。

以下是es对该方法定义的截图,图片看不清楚的童鞋可以看看链接 图片描述

嫌英文字母太多的可以直接看以下我写的slice方法的伪代码:

Array.prototype.slice = (start, end) => {
  let O = ToObject(this)
  let A = new Array()
  let lenVal = O.length
  let len = ToUnit32(lenVal)
  let relativeStart = ToInteger(start)
  let k, final, relativeEnd
  if (relativeStart < 0) {
    k = max(len + relativeStart, 0)
  } else {
    k = min(relativeStart, len)
  }
  if (end === undefined) {
    relativeEnd = len
  } else {
    relativeEnd = ToInteger(end)
  }
  if (relativeEnd < 0) {
    final = max(len + relativeEnd, 0)
  } else {
    final = min(relativeEnd, len)
  }
  let n = 0
  while (k < final) {
    let Pk = ToString(k)
    let kPresent = O.hasOwnProperty(Pk)
    if (kPresent) {
      let kValue = O[Pk]
      Object.defineProperty(A, ToString(n), {
        value: kValue,
        writable: true,
        enumerable: true,
        configurable: true
      })
    }
    k++
    n++
  }
  return A
}

ToObjectToUnit32ToIntegerToString slice 方法不要求 this 必须是数组,因此类数组对象也可以调用该方法,在本例中入参 startend 均为 undefined,实际上是根据 类数组对象 的 length 属性,从0到length-1去把类数组对象对应的值取出来,放到前面声明的数组 A 里,最终再return A 因此,类数组对象的 length 属性很重要,并且该对象里的数序也很重要,都会影响到转换为数组的结果。如以下例子:

let pretendArrA = {0:0, 1:1, 2:2, length:2};
[].slice.call(pretendArrA); //[0,1]

let pretendArrB = {0:0, 2:2, length:3};
[].slice.call(pretendArrB); //[0, undefined, 2]

第一次写文章,想到哪写到哪,写得有点乱,各位看官勿怪,如果对你有用,还请点个赞~

原文链接:https://segmentfault.com/a/1190000017292302

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-47512.html

文章标题:Array.prototype.slice.call 将伪数组转成真数组的原理是什么?

相关文章
从2014年的发展来展望JS的未来将会如何
&lt;font face=&quot;寰�杞�闆呴粦, Arial, sans-serif &quot;&gt;2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
12个你未必知道的CSS小知识
虽然CSS并不是一种很复杂的技术,但就算你是一个使用CSS多年的高手,仍然会有很多CSS用法/属性/属性值你从来没使用过,甚至从来没听说过。 1.CSS的color属性并非只能用于文本显示 对于CSS的color属性,相信所有Web开发人员...
2015-11-12
ajax为什么令人惊异?ajax的优缺点
使用Ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变的信息。 Ajax不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。就像DHT...
2015-11-12
HTML5的5个不错的开发工具推荐
HTML5规范终于在今年正式定稿,对于从事多年HTML5开发的人员来说绝对是一个重大新闻。数字天堂董事长,DCloud CEO王安也发表了文章,从开发者和用户两个角度分析了HTML对两个人群的优势。其实,关于HTML5的开发工具,我们以往的...
2015-11-12
JavaScript教程:JS中的原型
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。 标准方法(The Standard Way) 一直以来,我们学习的在 JavaScript 里创建对...
2015-11-12
javascript是什么意思
avaScript是Netscape开发的一个对象脚本语言,它使用在世界各地数以百万计的网页和服务器应用程序上。 网景的JavaScript是ecma - 262版的标准脚本语言,和公布的标准只有轻微的差异。 与广为流行的错误理解相反,Ja...
2015-11-12
AJAX的浏览器支持
AJAX 的要点是 XMLHttpRequest 对象。 不同的浏览器创建 XMLHttpRequest 对象的方法是有差异的。 IE 浏览器使用 ActiveXObject,而其他的浏览器使用名为 XMLHttpRequest 的 Jav...
2015-11-12
JavaScript的组成
一个完整的JavaScript由3个部分组成:核心(ECMAScript) 文档对象模型(DOM) 浏览器对象模型(BOM) ECMAScript 描述了该语言的语法和基本对象 ; DOM 描述了处理网页内容的方法和接口 ; BOM 描...
2015-11-12
typeof、instanceof和contructor的区别
typeof:以字符串的形式返回变量的原始类型,typeof在两种情况下会返回&quot;undefined&quot;:一个变量没有被声明的时候,和一个变量的值是undefined的时候,注意,typeof null也会返回object,...
2015-11-12
Riot.js:不足1KB的MVP客户端框架
Riot.js是一款MVP(模型-视图-呈现)开源客户端框架,其最大的特点就是体积非常小,不足1KB,虽然体积小,但它可以帮助用户构建大规模的Web应用程序。 Riot.js是由Moot公司开发,目前最新版本为v0.9.2,遵循MIT开源许...
2016-03-11
回到顶部