美文网首页前端攻城狮
[].slice.call() 原理分析

[].slice.call() 原理分析

作者: 花泽冒菜 | 来源:发表于2018-10-07 18:51 被阅读0次

    [].slice.call() 常用来将类数组转化为真正的数组。要理解其中的原理,必须了解以下几个知识点:

    • 继承
      这里的空数组是Array构造函数的实例,继承了Array.prototype的slice()方法,因此有以下关系:
      [].slice() === Array.prototype.slice(); // true

    • 函数的call()方法
      call()方法是得以转化的关键所在。
      call()是所有函数都具备的方法,其作用有两个,即调用函数并改变函数内部this指向。

      - 调用函数
      调用 调用call()方法的这个函数,例如:fn.call()可以粗略的理解为fn()(暂时先不考虑参数的情况下)。
      - 改变函数内部this指向
      将函数fn内部的this指向call()方法的第一个对象参数,这么做的意义是可以使这个对象把fn这个函数(或者说方法)据为己有。

    • 数组的slice()方法
      MDN的解释是:

      slice() 方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象。且原始数组不会被修改。

      也就是说,slice用来截取一部分数组元素并返回新数组。接收两个可选参数,表示目标数组的下标范围:[begin, end)。begin省略则默认为0,end省略默认一直截取到数组末尾。

    再回过头看[].slice.call(),如果传入一个类数组

    var arrayLike = {
      0: 'a',
      1: 'b',
      2: 'c',
      length: 3
    }
    

    [].slice.call(arrayLike)将经历这些步骤:让arrayLike拥有数组的slice方法,slice方法被调用,其作用目标为arrayLike,由于没有传入其他参数,slice()默认返回所有下标的元素并返回新数组,最终得到:

    var array = [].slice.call(arrayLike);
    array;  // ['a', 'b', 'c']
    

    通过上文分析,我们知道apply和call具有同样的作用,那为什么不用apply呢?两者的区别在于传参的形式,从第二个参数开始(都是可选参数),都会成为调用的函数的参数,call接收一个个参数,而apply接收一个由这些参数组成的数组。如果只是原封不动的转换成数组的话,用apply和call没有任何区别,如果在转换的过程中需要对slice传参,call就更合适了。

    相关文章

      网友评论

        本文标题:[].slice.call() 原理分析

        本文链接:https://www.haomeiwen.com/subject/jlalaftx.html