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. php中使用swoole实现头协议

    当需要有数据交互的时候,为了安全起见,双方会协商一个固定的头协议,这样必须实现其头协议才能拿到数据. PHP的swoole完美的提供了固定包头+包体协议自动分包. 首先需要通过open_length_ ...

  2. Spring Data 整合 ElasticSearch搜索服务器

    一.基于 maven 导入坐标(pom.xml文件) <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi ...

  3. HTTP 2 新特性

    HTTP 2 新特性 HTTP/2 不是彻底的重写http协议,HTTP methods,status codes 和 语义化都是相同的,并且它应该使用和HTTP/1.x 相同的api 表示协议. H ...

  4. codeforces #446 892A Greed 892B Wrath 892C Pride 891B Gluttony

    A  链接:http://codeforces.com/problemset/problem/892/A 签到 #include <iostream> #include <algor ...

  5. PHP 算法

    1.首先来画个菱形玩玩,很多人学C时在书上都画过,咱们用PHP画下,画了一半. 思路:多少行for一次,然后在里面空格和星号for一次. ? 1 2 3 4 5 6 <?php for($i=0 ...

  6. Java数据结构和算法(八)——递归

    记得小时候经常讲的一个故事:从前有座山,山上有座庙,庙里有一个老和尚和一个小和尚,一天,老和尚给小和尚讲了一个故事,故事内容是“从前有座山,山上有座庙,庙里有一个老和尚和一个小和尚,一天,老和尚给小和 ...

  7. 天天乐宝APP开发

    "互联网+"时代是一个"信息过剩"的时代,也是一个"注意力稀缺"的时代,怎样在"无限的信息中"获取"有限的注意 ...

  8. Backbone简单示例

    要的资源: <script type="text/javascript" src="../dep/underscore-1.6.0.min.js"> ...

  9. OJ随笔——【1088-N!】——同余定理

    题目如下: Description 请求N!(N<=10000),输出结果对10007取余输入每行一个整数n,遇到-1结束.输出每行一个整数,为对应n的运算结果.   Sample Input ...

  10. db2 update 异常

    报错: -错误的sql语句:update Persons SET FirstName = 'Fred' WHERE id_P = 1com.ibm.db2.jcc.am.SqlException: O ...