美文网首页Web 前端开发 让前端飞
理解Array.prototype.slice.call()

理解Array.prototype.slice.call()

作者: 大海爱奔跑 | 来源:发表于2020-02-24 11:09 被阅读0次

    晚上看张鑫旭老师的一篇文章,发现[].splice.call()这样的用法,很感兴趣,因为昨天刚写完一篇关于call方法的博客《一文读懂js中的call和apply》(以下简称“《call》”),想一探究竟,也正好加深对call的理解。

    基础:

    1. slice()方法可以从已有的数组中返回选定的元素,语法:array.slice(start, end),截取array中第start位到第end位之间的部分,范围:[start, end);
    2. slice()的参数可以省略,省略时默认从0开始,一直到最后一位,也就是返回全部;
    3. call和apply的作用都是在特定作用域中调用函数,例如:程序员.编程.call(外卖员)就是在外卖员作用域中调用程序员的编程方法,即外卖员编程。

    探索:

    张老师[].slice.call(eleRadios)这么写是想让eleRadios调用数组的原生方法slice()从而转换成数组格式,那么eleRadios本身不是数组吗?非得绕这么一大圈?下面贴出他的部分代码(完整版点击这里):

    // 已删除部分无关代码
    <input type="radio" value="default" checked>
    <input type="radio" value="red">
    <input type="radio" value="green">
    
    var eleRadios = document.querySelectorAll('input[type="radio"]');
    [].slice.call(eleRadios).forEach(function (radio) {
        radio.addEventListener('click', function () {
            // 略
        });
    });
    

    通过document.querySelectorAll获取页面上所有type等于“radio”的input的节点集合eleRadios,接着对[].slice.call(eleRadios)进行forEach遍历,给其中每个子元素添加click点击事件。为什么不能直接调用forEach方法——就像这样eleRadios.forEach(...)?看来eleRadios真不是数组?于是我在页面上的调试工具console中测试了一下,发现猜想是对的:

    通过打印,得知eleRadiosNodeList类型,为了再次验证它与数组的关系,我还使用instanceof的方式进行检测,结果一目了然:不是数组。

    如果你在chrome等一些较新的浏览器上测试,会发现 NodeList 类型是可以调用 forEach() 的,但是这一特性并不稳定,在低版本浏览器上 NodeList 并不支持 forEach() ,所以,张鑫旭老师这样写应该是为了解决兼容问题。在实际开发中,我们最好使用 [].slice.call() 将其转换成数组类型再调用数组的一些方法,这样比较稳妥。

    原理:

    现在就清楚了,为了能遍历这个NodeList类型的eleRadios,就使用call方法啦:eleRadios这个作用域中调用数组的slice方法,以转化成数组类型,然后调用forEach方法实现遍历。

    因为[]是Array的实例,所以也可以写成[].slice.call()


    2019年12月25日圣诞节补充

    类数组转数组的ES6写法:

    const arr = Array.from(eleRadios)
    const arr = [...eleRadios]
    

    相关文章

      网友评论

        本文标题:理解Array.prototype.slice.call()

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