很多框架或者库里面都会有这句的使用,最多的还是通过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)。

(转)Array.prototype.slice.call自解的更多相关文章

  1. 【javascript 技巧】Array.prototype.slice的妙用

    Array.prototype.slice的妙用 开门见山,关于Array 的slice的用法可以参考这里 http://www.w3school.com.cn/js/jsref_slice_arra ...

  2. Array.prototype.slice.call(arguments)

    Array.prototype.slice.call(arguments)能够将具有length属性的对象转化为数组, 可以理解为将arguments转化成一个数组对象,让它具有slice方法 如: ...

  3. IE下Array.prototype.slice.call(params,0)

    i8 不支持 Array.prototype.slice.call(params,0) params可以是 HTMLCollection.类数组.string字符串

  4. 详解 Array.prototype.slice.call(arguments)

    首先,slice有两个用法,一个是String.slice,一个是Array.slice,第一个返回的是字符串,第二个返回的是数组 在这里我们看第二个方法 1.在JS里Array是一个类 slice是 ...

  5. Array.prototype.slice && Array.prototype.splice 用法阐述

    目的 对于这两个数组操作接口,由于不理解, 往往被误用, 或者不知道如何使用.本文尝试给出容易理解的阐述. 数组 什么是数组? 数组是一个基本的数据结构, 是一个在内存中依照线性方式组织元素的方式, ...

  6. Array.prototype.slice.call(document.querySelectorAll('a'), 0)

    Array.prototype.slice.call(document.querySelectorAll('a'), 0)的作用就是将一个DOM NodeList 转换成一个数组. slice()方法 ...

  7. Array.prototype.slice.call

    Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组 ,::'age'}; Array.prototype.slice.call(arr); ...

  8. Array.prototype.slice.call(arguments) 类数组转成真正的数组

    Array.prototype.slice.call(arguments)   我们知道,Array.prototype.slice.call(arguments)能将具有length属性的对象转成数 ...

  9. JavaScript 兼容 Array.prototype.slice.call

    IE9之前的IE版本的HTMLCollection以及NodeList不是Object的子类. 在通过Array.prototype.slice.call进行数组化的时候,IE9之前的IE版本会抛出异 ...

随机推荐

  1. Linux安装mysql最新版本纪要

    http://blog.csdn.net/frt007/article/details/50184143 http://blog.csdn.net/wb96a1007/article/details/ ...

  2. ****php:require_once(dirname(__FILE__)."/./config_uc.php");

    Q:麻烦清楚地讲解一下这句的意思,具体路径是怎样的,这个文解在 根目录,如果我想放在根目录下的tieba文件夹里,应该怎么修改/./ 这个是表示什么? A: require_once(dirname( ...

  3. jQuery ajax同步的替换方法,使用 $.Deferred()对象

    function aa() { var defer = $.Deferred(); $.ajax({ url: "/Handler1.ashx", type: "post ...

  4. subversion安装使用

    这里仅针对subversion进行说明,未完待续. 一.下载subversion并安装: a.subversion 要做svn服务器的必须装 b.Tortoisesvn 仅仅是访问svn服务器的客户端 ...

  5. Oracle 备份与恢复介绍

    一.Oracle备份方式分类:Oracle有两类备份方式:(1)物理备份:是将实际组成数据库的操作系统文件从一处拷贝到另一处的备份过程,通常是从磁盘到磁带.物理备份又分为冷备份.热备份:   (2)逻 ...

  6. wp8 入门到精通 ---转换

             /// <summary>        /// 颜色字符串转Color        /// </summary>        public static ...

  7. 二叉搜索树的实现及指针问题的一点思考(C++)

    今天实现二叉搜索树的时候因为指针的问题卡了一上午(实在不应该...),一直segmentation fault,个人感觉还是需要记录一下的. 首先贴一下做的题的意思: 输入一系列整数,建立二叉排序数, ...

  8. linux使用读写锁pthread_rwlock_t

    转自:http://blog.csdn.net/onlyou930/article/details/6755593 使用读写锁 配置读写锁的属性之后,即可初始化读写锁.以下函数用于初始化或销毁读写锁. ...

  9. linux系统定时任务

    crontab常用的几个命令如下 sudo crontab -l #显示所有的定时任务 sudo crontab -e #编辑任务 sudo crontab -r #删除所有的任务 编辑任务时的书写方 ...

  10. 在Asp.Net MVC中实现CompareValues标签对Model中的属性进行验证

    在Asp.Net MVC中可以用继承ValidationAttribute的方式,自定制实现Model两个中两个属性值的比较验证 具体应用场景为:要对两个属性值的大小进行验证 代码如下所示: /// ...