资讯专栏INFORMATION COLUMN

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

shinezejian / 3114人阅读

摘要:好久没上,昨天上来看到一个问题,引起了我的兴趣。请看上面的例子可能很多前端童鞋都很知道可以用于将类数组对象转为数组,和的用法和作用网上一搜一大堆。在这里主要是为了让借用构造函数原型上的方法,并且改变方法里的的指向。

好久没上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
}

ToObject、ToUnit32、ToInteger、ToString
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://www.ucloud.cn/yun/99805.html

相关文章

  • 数组及其换为真数组原理

    摘要:伪数组及其转换为真数组原理什么是伪数组定义拥有属性和数值下标属性。不具有数组所具有的方法。伪数组是一个,而真实的数组是一个常见的伪数组参数数组对象列表比如通过得到的列表对象比如举例通过得到的对象列表是一个伪数组。 伪数组及其转换为真数组原理 什么是伪数组 定义: 拥有length属性和数值下标属性。 不具有数组所具有的方法。 伪数组是一个Object,而真实的数组是一个Array ...

    fobnn 评论0 收藏0
  • 深入理解 Javascript 之 this

    摘要:深入浅出的理解问题的由来写法一写法二虽然和指向同一个函数,但是执行结果可能不一样。该变量由运行环境提供。所以,就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。 深入浅出this的理解 问题的由来 var obj = { foo: function(){} } var foo = obj.foo; // 写法一 obj.foo(); // 写法二 foo...

    OnlyMyRailgun 评论0 收藏0
  • 将伪数组换为数组几个方法

    摘要:第一个借用数组的方法请输入代码第二个新增的一个方法第三个原型将对象转换为数组 第一个借用数组的slice方法 var a ={ 0:t, 1:a, 2:r, length:3 } let b=Array.prototype.slice.call(a); console.log(b) 请输入代码 第二...

    陆斌 评论0 收藏0
  • 【进阶3-3期】深度解析 call 和 apply 原理、使用场景及实现

    摘要:之前文章详细介绍了的使用,不了解的查看进阶期。不同的引擎有不同的限制,核心限制在,有些引擎会抛出异常,有些不抛出异常但丢失多余参数。存储的对象能动态增多和减少,并且可以存储任何值。这边采用方法来实现,拼成一个函数。 之前文章详细介绍了 this 的使用,不了解的查看【进阶3-1期】。 call() 和 apply() call() 方法调用一个函数, 其具有一个指定的 this 值和分...

    godlong_X 评论0 收藏0
  • JavaScript基础知识整理(1)

    摘要:从这段描述可以得到以下对象小芒和小贤一样,原来也是一条可爱的小狗,可是突然有一天疯了,一看到人就会每隔半秒叫一声地不停叫唤。将一个函数的对象上下文从初始的上下文改变为由指定的新对象。 1、JavaScript数据类型有哪些? 基本数据类型:Number、String、Boolean、Null、Undefined 引用数据类型:Object(Array、Date、RegExp、Funct...

    macg0406 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<