zoukankan      html  css  js  c++  java
  • (转)Array.prototype.slice.call自解

    很多框架或者库里面都会有这句的使用,最多的还是通过Array.prototype.slice.call(arguments,0)把arguments这个伪数组转换为真正的数组。但为什么可以这么做,却一直是半懂不懂的。昨天晚上看了mootools的源码,google了一下,终于彻底明白了。

    call方法的作用就不用多说了,Array.prototype.slice.call(arguments,0)就类似于arguments.slice(0),但因为arguments不是真正的Array,所以它没有slice这个方法.能用slice方法的,只要有length属性就行。虽然arguments有length属性,但是没有slice方法,所以呢,Array.prototype.slice()执行的时候,Array.prototype已经被call改成arguments了,因为满足slice执行的条件(有length属性),所以没有报错。

    为了研究Currying in Javascript,翻阅了很多外文网站,为的是找一个比较好的Currying方案,找到的比较详细的有如下(文章内部链接可能包含更多的相关文章): 

       1. Currying JavaScript Functions 
       2. JavaScript Currying Redux 
       3. JavaScript currying 
       4. functional.js 介绍及源码分析 

    发现大多人都用了Array.prototype.slice.call(argments,0),一直不明白这句是干什么的。而昨天温习了slice()方法,再参考Function.call(thisArg[, arg1[, arg2[, ...]]]),还是不得而知(我脑筋转得慢:|)。上网查,第一时间查老外的Google.com in English也没解释,真到查找“Array.prototype.slice 用法”时,才得到数篇。虽然我很鄙视搞收集的人,搞得互联网文章像是天下一大抄似的,但现在却恨少,只得三篇(一模一样的三篇,责任编辑为admin或者超级管理员,作者是佚名。) 

    下面就我的理解,对Array.prototype.slice.call进行解说,菜鸟留下,大虾吐口水: 
    Update: 下面写的可能有点难懂,怕刚接触Javascript的人可能会看不懂,请大家看完后留个言,谢谢! 
    Array.prototype.slice.call(thisArg[, arg1[, arg2[, ...]]]) 

    成员介绍: 
    Array [object] 

    Array对象(即数组对象) 
    prototype [property] 

    Javascript的原型,此prototype非Prototype.js,可以暂且理解为Java中的静态属性/方法。总之这个不好说,详细请看这里。 
    slice [Function] 

    数组切分方法,很有用的一个方法,具体请看这里,或那里。 
    call [Function] 

    神奇的方法,该方法是所有Function对象里的方法,所以slice就有这样一个方法。用于把Function对象里的this替换为目标对象。看这里。 

    串起来就是: 

    用人类的语言说,就是Array有个prototype,slice是prototype的儿子,call是slice的妻子(很多砖头飞过来。)请继续往下看。 

    作用效果: 
    Array.prototype.slice.call == [].slice 

    虽然运行结果是一个样的,但经过试验(别人做的试验,不是我),前者的运行效率比后者大大提高,所以就这样应用。 

    机理: 
    这里的slice方法就是一个Function对象。通常情况下,程序员通过如下方法调用Function,实质是普通的函数调用方法: 

    Array.slice(begin,end) 

    至于call()方法,METHOD: Function::call告诉我们,可以通过 

    Function.call(thisArg[, arg1[, arg2[, ...]]]) 

    的形式调用一个Function对象,把当中的this对象替换为thisArg,即可以得到下面的代码: 

    Array.prototype.slice.call(obj,begin,end) 

    用伪代码模拟过程: 

    好,我们用伪代码的方法来模拟整个过程: 

    1 var mySlice=Array.prototype.slice; 

    2 alert(mySlice); //alert: function(begin[,end]){...},这是个“函数” 

    3 var array_empty=mySlice(begin,end); //create a new,empty array 

    4 set array_empty=obj; //此时,把obj赋给这个空的数组,使数组有了种子, 
                                  //这就是call()所做的事,“人工受精” 

    5 alert(array_empty); //这是个未定型的数组对象,由Javascript内部掌控着, 
                               //这样看可能没什么结果,但有结果的话,就一定与obj有关 

    //下面是关键的一行: 
    6 var array_last=array_empty.slice(begin,end); 
    /** 
    *虽然之前说未定型, 
    *但返回的已经是一个数组了,我们对数组进行切割,但拿什么进行切? 
    *没错,就拿用obj制造出来的数组进行切割, 
    *一个新的数组对象产生了! 
    */ 




    同样,Array.prototype.slice.apply(obj)及类似的代码也可以这样理解,只要不被prototype干扰到就行了。看到这里还不明白的人请重温Array.slice(begin,end)。 

  • 相关阅读:
    Grafana+Prometheus监控mysql性能
    性能测试监控平台Grafana的使用
    搭建grafana+telegraf+influxdb服务器性能监控平台
    cocos2d-x jsb 防止触摸事件传递
    web app 相关记录
    如何在Teamcenter中使用PMI?
    浅谈人机工程应用在数字化工艺中的作用
    关于奇葩说
    一些感想
    关于起名
  • 原文地址:https://www.cnblogs.com/chris-oil/p/5042077.html
Copyright © 2011-2022 走看看