【 js 基础 】为什么 call 比 apply 快?
这是一个非常有意思的问题。
在看源码的过程中,总会遇到这样的写法:
var triggerEvents = function(events, args) {
var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
switch (args.length) {
case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
}
};
( 代码来自 backbone )


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 方法的参数格式正是内部方法所需要的格式。

【 js 基础 】为什么 call 比 apply 快?的更多相关文章
- js基础篇——call/apply、arguments、undefined/null
a.call和apply方法详解 call方法: 语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象 ...
- 前端工程师面试问题归纳(一、问答类html/css/js基础)
一.参考资源 1.前端面试题及答案整理(一) 2.2017年前端面试题整理汇总100题 3.2018最新Web前端经典面试试题及答案 4.[javascript常见面试题]常见前端面试题及答案 5.W ...
- JS中的call、apply、bind方法
JS中的call.apply.bind方法 一.call()和apply()方法 1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[, [,.argN]]] ...
- js基础查漏补缺(更新)
js基础查漏补缺: 1. NaN != NaN: 复制数组可以用slice: 数组的sort.reverse等方法都会改变自身: Map是一组键值对的结构,Set是key的集合: Array.Map. ...
- js基础进阶--关于Array.prototype.slice.call(arguments) 的思考
欢迎访问我的个人博客:http://www.xiaolongwu.cn Array.prototype.slice.call(arguments)的作用为:强制转化arguments为数组格式,一般出 ...
- 前端面试题目汇总摘录(JS 基础篇)
JS 基础 JavaScript 的 typeof 返回那些数据类型 object number function boolean undefined string typeof null; // o ...
- js基础面试篇
1,js中的new做了什么? function Person () { this.name = name; this.age = age; this.sex = sex this.sayName = ...
- js基础梳理-关于this常见指向问题的分析
首先,依然回顾<js基础梳理-究竟什么是执行上下文栈(执行栈),执行上下文(可执行代码)?>中的 3.执行上下文的生命周期 3.1 创建阶段 生成变量对象(Variable object, ...
- 为什么call比apply快
这是一个非常有意思的问题. 在看源码的过程中,总会遇到这样的写法: var triggerEvents = function(events, args) { var ev, i = -1, l = e ...
随机推荐
- lua breakpoint
http://blog.codingnow.com/2016/11/lua_debugger.html It aims to separate debug code from host code. A ...
- svn 设置 excel 比对工具为 SPREADSHEETCOMPARE.EXE
http://blog.csdn.net/ccpat/article/details/50725774
- es6 学习小记 扩展运算符 三个点(...)
参考: es6 扩展运算符 三个点(...) 经常回顾,方能真正掌握. 一.含义 扩展运算符( spread )是三个点(...).它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列. ...
- MySQL 逻辑物理备份测试
目录 逻辑备份 mysqldump 普通备份 mysqlpump 并行备份 mysqlpump 压缩并行备份 mydumper 并行备份 mydumper 并行压缩备份 小结 物理备份 xtrabac ...
- MySQL 并行复制(MTS) 从库更新的记录不存在实际却存在
目录 背景 版本 分析 测试 背景 开了并行复制的半同步从库SQL 线程报1032错误,异步复制从库没有报错,偶尔会出现这种 版本 mysql 5.7.16 redhat 6.8 mysql> ...
- ThinkPHP5代码执行的简单分析
漏洞影响版本: ThinkPHP 5.0.5-5.0.22 ThinkPHP 5.1.0-5.1.30 漏洞复现: 一.mac的debug环境搭建. 一键化环境搭建工具: mamp pro ,调试工具 ...
- java里面main函数为什么要用static修饰
这学期刚开java,因为之前只写过C++和Python没接触过java,有些写法挺不习惯的,今天写完一个程序,run的时候发现提示the selection can't be launched.... ...
- node.js中的回调
同步和阻塞:这两个术语可以互换使用,指的是代码的执行会在函数返回之前停止.如果某个操作阻塞,那么脚本就无法继续,这意味着必须等待. 异步和非阻塞:这两个术语可以互换使用,指的是基于回调的.允许脚本并行 ...
- 同时绑定onpropertychange 和 oninput 事件,实时检测 input、textarea输入改变事件,支持低版本IE,支持复制粘贴
实时检测 input.textarea输入改变事件,支持低版本IE,支持复制粘贴 检测input.textarea输入改变事件有以下几种: 1.onkeyup/onkeydown 捕获用户键盘输入事件 ...
- String、StringBuffer与StringBuilder之间区别 (转载)
最近学习到StringBuffer,心中有好些疑问,搜索了一些关于String,StringBuffer,StringBuilder的东西,现在整理一下. 关于这三个类在字符串处理中的位置不言而喻,那 ...