博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【 js 基础 】为什么 call 比 apply 快?
阅读量:4625 次
发布时间:2019-06-09

本文共 2104 字,大约阅读时间需要 7 分钟。

这是一个非常有意思的问题。

在看源码的过程中,总会遇到这样的写法:

1 var triggerEvents = function(events, args) { 2     var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; 3     switch (args.length) { 4       case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; 5       case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return; 6       case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return; 7       case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return; 8       default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return; 9     }10 };

( 代码来自 backbone )

作者会在参数为3个(包含3)以内时,优先使用 call 方法进行事件的处理。而当参数过多(多余3个)时,才考虑使用 apply 方法。
这个的原因就是 call 比 apply 快。 
 
网上有很多例子全方位的证明了 call 比 apply 快。大家可以看看  这篇文章中的例子,很全面。或者你也可以自己写几个简单的,测试一下。这里要推荐一个神奇网站  ,用于测试 js 性能。
 
几个简单的例子:

 
 
为什么call 比apply 快?
这里就要提到他们被调用之后发生了什么。 
 

Function.prototype.apply (thisArg, argArray)

1、如果IsCallable(Function)为false,即Function不可以被调用,则抛出一个TypeError异常。

2、如果argArray为null或未定义,则返回调用function的[[Call]]内部方法的结果,提供thisArg和一个空数组作为参数。
3、如果 Type(argArray)不是Object,则抛出TypeError异常。
4、获取argArray的长度。调用argArray的[[Get]]内部方法,找到属性length。 赋值给len。
5、定义 n 为ToUint32(len)。ToUint32(len)方法:将其参数len转换为范围为0到2^32-1的2^32个整数值中的一个。
6、初始化 argList 为一个空列表。
7、初始化 index 为 0。
8、循环迭代取出argArray。重复循环 while(index < n)
            a、将下标转换成String类型。初始化 indexName 为 ToString(index).
            b、定义 nextArg 为 使用 indexName 作为参数调用argArray的[[Get]]内部方法的结果。
            c、将 nextArg 添加到 argList 中,作为最后一个元素。
            d、设置 index = index+1
9、返回调用func的[[Call]]内部方法的结果,提供thisArg作为该值,argList作为参数列表。

 

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

1、如果 IsCallable(Function)为false,即Function不可以被调用,则抛出一个TypeError异常。

2、定义argList 为一个空列表。
3、如果使用超过一个参数调用此方法,则以从arg1开始的从左到右的顺序将每个参数附加为argList的最后一个元素
4、返回调用func的[[Call]]内部方法的结果,提供thisArg作为该值,argList作为参数列表。

我们可以看到,明显apply比call的步骤多很多。
由于apply中定义的参数格式(数组),使得被调用之后需要做更多的事,需要将给定的参数格式改变(步骤8)。 同时也有一些对参数的检查(步骤2),在call中却是不必要的。
另外一个很重要的点:在apply中不管有多少个参数,都会执行循环,也就是步骤6-8,在call中也就是对应步骤3 ,是有需要才会被执行。

综上,call 方法比 apply 快的原因是 call 方法的参数格式正是内部方法所需要的格式。

 

 

 

 
参考并学习:
 
 
 

转载于:https://www.cnblogs.com/lijiayi/p/callandapply.html

你可能感兴趣的文章
PHP和MYSQL中的日期和时间
查看>>
变量初始化,基类构造器,基类构造器中调用虚函数,子类构造器
查看>>
极其蛋疼的if else 中的break用法
查看>>
Map集合
查看>>
C#/java 执行oracle package
查看>>
程序面试试题
查看>>
Wall POJ - 1113 凸包模板
查看>>
leetcode算法: Find Bottom Left Tree Value
查看>>
python opencv3 grabcut前景检测
查看>>
内容安全策略(CSP)_防御_XSS_攻击的好助手
查看>>
获取URL中的参数
查看>>
宝塔面板安装swoole扩展
查看>>
HDOJ_1061_Rightmost Digit
查看>>
【小笨鸟看JDK1.7集合源码之三】LinkedList源码剖析
查看>>
bfs,dfs区别
查看>>
Javascript端加密java服务端解密
查看>>
xml文件中引号如何处理
查看>>
Centos 下 Jenkins2.6 + Git + Maven Shell一件部署与备份
查看>>
MVC原理
查看>>
Java中堆内存和栈内存详解
查看>>