apply 和 call 的区别

ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已。

原文作者:林鑫,作者博客:https://github.com/lin-xin/blog

apply( )

apply 方法传入两个参数:一个是作为函数上下文的对象,另外一个是作为函数参数所组成的数组。

var obj = {
name : 'linxin'
} function func(firstName, lastName){
console.log(firstName + ' ' + this.name + ' ' + lastName);
} func.apply(obj, ['A', 'B']); // A linxin B

可以看到,obj 是作为函数上下文的对象,函数 func 中 this 指向了 obj 这个对象。参数 A 和 B 是放在数组中传入 func 函数,分别对应 func 参数的列表元素。

call( )

call 方法第一个参数也是作为函数上下文的对象,但是后面传入的是一个参数列表,而不是单个数组。

var obj = {
name: 'linxin'
} function func(firstName, lastName) {
console.log(firstName + ' ' + this.name + ' ' + lastName);
} func.call(obj, 'C', 'D'); // C linxin D

对比 apply 我们可以看到区别,C 和 D 是作为单独的参数传给 func 函数,而不是放到数组中。

对于什么时候该用什么方法,其实不用纠结。如果你的参数本来就存在一个数组中,那自然就用 apply,如果参数比较散乱相互之间没什么关联,就用 call。

apply 和 call 的用法

1.改变 this 指向

var obj = {
name: 'linxin'
} function func() {
console.log(this.name);
} func.call(obj); // linxin

我们知道,call 方法的第一个参数是作为函数上下文的对象,这里把 obj 作为参数传给了 func,此时函数里的 this 便指向了 obj 对象。此处 func 函数里其实相当于

function func() {
console.log(obj.name);
}

2.借用别的对象的方法

先看例子

var Person1  = function () {
this.name = 'linxin';
}
var Person2 = function () {
this.getname = function () {
console.log(this.name);
}
Person1.call(this);
}
var person = new Person2();
person.getname(); // linxin

从上面我们看到,Person2 实例化出来的对象 person 通过 getname 方法拿到了 Person1 中的 name。因为在 Person2 中,Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象,那么 Person2 就有了 Person1 中的所有属性和方法了,相当于 Person2 继承了 Person1 的属性和方法。

3.调用函数

apply、call 方法都会使函数立即执行,因此它们也可以用来调用函数。

function func() {
console.log('linxin');
}
func.call(); // linxin

call 和 bind 的区别

在 EcmaScript5 中扩展了叫 bind 的方法,在低版本的 IE 中不兼容。它和 call 很相似,接受的参数有两部分,第一个参数是是作为函数上下文的对象,第二部分参数是个列表,可以接受多个参数。

它们之间的区别有以下两点。

1.bind 发返回值是函数

var obj = {
name: 'linxin'
} function func() {
console.log(this.name);
} var func1 = func.bind(obj);
func1(); // linxin

bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 func 中的 this 并没有被改变,依旧指向全局对象 window。

2.参数的使用

function func(a, b, c) {
console.log(a, b, c);
}
var func1 = func.bind(null,'linxin'); func('A', 'B', 'C'); // A B C
func1('A', 'B', 'C'); // linxin A B
func1('B', 'C'); // linxin B C
func.call(null, 'linxin'); // linxin undefined undefined

call 是把第二个及以后的参数作为 func 方法的实参传进去,而 func1 方法的实参实则是在 bind 中参数的基础上再往后排。

在低版本浏览器没有 bind 方法,我们也可以自己实现一个。

if (!Function.prototype.bind) {
Function.prototype.bind = function () {
var self = this, // 保存原函数
context = [].shift.call(arguments), // 保存需要绑定的this上下文
args = [].slice.call(arguments); // 剩余的参数转为数组
return function () { // 返回一个新函数
self.apply(context,[].concat.call(args, [].slice.call(arguments)));
}
}
}

下一篇介绍闭包:JavaScript 中 闭包 的详解

更多文章:lin-xin/blog

JavaScript 中 apply 、call 的详解的更多相关文章

  1. javascript中的this作用域详解

    javascript中的this作用域详解 Javascript中this的指向一直是困扰我很久的问题,在使用中出错的机率也非常大.在面向对象语言中,它代表了当前对象的一个引用,而在js中却经常让我觉 ...

  2. javascript中=、==、===区别详解

    javascript中=.==.===区别详解今天在项目开发过中发现在一个小问题.在判断n==""结果当n=0时 n==""结果也返回了true.虽然是个小问题 ...

  3. JavaScript中return的用法详解

    JavaScript中return的用法详解 最近,跟身边学前端的朋友了解,有很多人对函数中的this的用法和指向问题比较模糊,这里写一篇博客跟大家一起探讨一下this的用法和指向性问题. 1定义 t ...

  4. javascript 中合并排序算法 详解

    javascript 中合并排序算法 详解 我会通过程序的执行过程来给大家合并排序是如何排序的...  合并排序代码如下: <script type="text/javascript& ...

  5. JavaScript中this的用法详解

    JavaScript中this的用法详解 最近,跟身边学前端的朋友了解,有很多人对函数中的this的用法和指向问题比较模糊,这里写一篇博客跟大家一起探讨一下this的用法和指向性问题. 1定义 thi ...

  6. JavaScript中数组Array方法详解

    ECMAScript 3在Array.prototype中定义了一些很有用的操作数组的函数,这意味着这些函数作为任何数组的方法都是可用的. 1.Array.join()方法 Array.join()方 ...

  7. JavaScript中的注释问题详解? 部分3

    注释:解释代码的含义,浏览器中不执行. 方便其他程序员了解代码 ,也可以注释自己不需要的代码(开发过程中)! 1. 单行注释 // 用于一行代码上面 2.多行注释 /* */ 用于一段代码上面 或者是 ...

  8. JavaScript中的async/await详解

    1.前言 ​ async函数,也就是我们常说的async/await,是在ES2017(ES8)引入的新特性,主要目的是为了简化使用基于Promise的API时所需的语法.async和await关键字 ...

  9. Javascript中prototype属性的详解

    原文链接:http://www.cnblogs.com/Uncle-Keith/p/5834289.html 在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象 ...

  10. JavaScript中的execCommand()命令详解及实例展示

    execCommand方法是执行一个对当前文档,当前选择或者给出范围的命令.处理Html数据时常用如下格式:document.execCommand(sCommand[,交互方式, 动态参数]) ,其 ...

随机推荐

  1. 为什么ERP行业发展缓慢规模难扩大?

    题记:这个行业只会越来越好,但是能沉淀下来做事儿的企业越来越少,因为收益真的很漫长:能够真正进入这个行业难,出去也难... 经常在知乎上看到类似的问题:既然所有ERP系统都很烂,那有没有创业公司的空间 ...

  2. Python 学习之路3

    接下来把剩下的实验一起写上去 实验2 写一个学生类,属性有学号,姓名,成绩(三门),方法有输出,求平均成绩. 设计思路: 1.         先写一个学生类,并向里面写一个求平均值和输出信息的方法. ...

  3. windows配置caffe + python和matlab接口

    参考: http://blog.csdn.net/baidu_26408419/article/details/53711640 http://www.cnblogs.com/love6tao/p/5 ...

  4. head first python菜鸟学习笔记(第七章) ——web应用之为数据建模

    问题1. #意思是从athletelist.py中导入AthleteListfrom athletelist import AthleteList 源程序代码 import pickle from a ...

  5. Python 运行效率为何低

    当我们提到一门编程语言的效率时:通常有两层意思,第一是开发效率,这是对程序员而言,完成编码所需要的时间:另一个是运行效率,这是对计算机而言,完成计算任务所需要的时间.编码效率和运行效率往往是鱼与熊掌的 ...

  6. WPF开发的彩票程序(练手好例子) 附源码

    前言 WPF是.NET最新的界面开发库,开发界面非常灵活!但是学习WPF难度也非常大. 应朋友之邀,编写了一个小程序.程序虽小,五脏俱全,WPF开发的灵活性可窥见一斑. 对于新手学习有很好的借鉴意义, ...

  7. 二、Hadoop学习笔记————架构学习

    1.成百上千台服务器组成集群,需要时刻检测服务器是否故障 2.用流读取数据更加高效快速 3.存储节点具有运算功能,省略了服务器之间来回传数据的网络带宽限制 4.一次写入,多次访问,不修改数据 5.多平 ...

  8. sql关键词的执行顺序

    执行顺序:FROM>ON>JOIN>WHERE>GROUP BY>WITH CUBE or WITH ROLLUP>HAVING>SELECT>DIST ...

  9. poj 2456 Aggressive cows && nyoj 疯牛 最大化最小值 二分

    poj 2456 Aggressive cows && nyoj 疯牛 最大化最小值 二分 题目链接: nyoj : http://acm.nyist.net/JudgeOnline/ ...

  10. google guava cache缓存基本使用讲解

    代码地址:https://github.com/vikde/demo-guava-cache 一.简介 guava cache是google guava中的一个内存缓存模块,用于将数据缓存到JVM内存 ...