前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >call、apply和bind的区别

call、apply和bind的区别

作者头像
挥刀北上
发布2019-08-06 16:34:27
7090
发布2019-08-06 16:34:27
举报
文章被收录于专栏:Node.js开发Node.js开发
call、apply和bind这三个方法经常使用,但是具体有什么区别呢?

首先这三个方法的用法比较相似,但是作用,bind和前两者则完全不同。

call和apply是调用函数,bind却是返回一个新的函数。

下面看一下MDN对三者的解释:

call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表)。

apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数。

bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。

官方文档翻译的实在是语句不通啊,只能臆测加实现了。

总结一下共同点:

1、都是函数的方法。

2、都会通过传递第一个参数改变函数调用的this

3、都可以向函数传递参数。

那不同点呢,首先说一下call和apply的不同点。

call和apply的不同点只有一点,那就是向函数传递参数的方式不同。call是逐个的向函数传递参数,apply是通过将参数以数组的形式传递到函数中。代码如下:

代码语言:javascript
复制
// 通常状况下Max.max的参数是逐个分开的,如 Math.max(1,2,3,4,5,6,7)
// 但是现在有一个数组需要用Math.max获取最大值该如何做呢?
//  Math.max([1,2,3,4,5,6,7])这样肯定是不行的。这就用到了apply
let max = Math.max(1,2,3,4,5,6,7)
let maxApply = Math.max.apply(null,[1,2,3,4,5,6,7])
console.log(maxApply)

以上便是call和apply的不同了,除了这点不同其他就都相同了。

那call和apply如何改变函数的this呢,看代码:

代码语言:javascript
复制
var tim = { 
    name: 'tim', 
    age: 20, 
    getName: function() {
        console.log(this.name);
        return this.name; 
    }
}

var jake = { name: 'jake', age: 20 }

tim.getName(); // tim

// jake对象没有getName方法,但是可以通过call/apply去使用tim对象的getName方法
tim.getName.call(jake);  // jake 
tim.getName.apply(jake); // jake

大家需要注意的是,call和apply在改变函数this的同时,执行了函数,这点和bind是不同的,后面会说。

下面总结了call和apply的一些常用的地方。

1、将类数组形式转换为数组

代码语言:javascript
复制
// arguments
// 返回值为数组,arguments保持不变
var arg = [].slice.call(arguments);

// nodeList
var nList = [].slice.call(document.getElementsByTagName('li'));

2、方法借用,改变函数的this

代码语言:javascript
复制
var foo = {
    name: 'joker',
    showName: function() {
        console.log(this.name);
    }
};
var bar = {
    name: 'rose'
};

foo.showName.call(bar); // rose

3、在继承中应用

代码语言:javascript
复制
// parent
var Person = function(name) {
    this.name = name;
    this.gender = ['man', 'woman'];
}

// child
var Student = function(name, age) {

    // inherit
    Person.call(this);
}
Student.prototype.message = function() {
    console.log('name:'+this.name+', age:'+this.age+', gender:.'+this.gender[0]);
}

var xm = new Student('xiaom', 12);
xm.message(); //name:undefined, age:undefined, gender:.man

4、判断数据的类型

代码语言:javascript
复制
let arrayType = Object.prototype.toString.apply([])
let objType = Object.prototype.toString.apply({})
let stringType = Object.prototype.toString.apply("wwwww")
let numberType = Object.prototype.toString.apply(1111)
let nullType = Object.prototype.toString.apply(null)
let undefinedType = Object.prototype.toString.apply(c)
console.log(arrayType,objType,stringType,numberType,nullType,undefinedType)

上面的apply换成call也可以,打印结果如图:

call和apply的相同点和不同点说完了,下面看一看bind的用法,前面一直重申函数调用bind后返回一个新的函数。并不像call和apply,直接调用函数。执行如下代码:

代码语言:javascript
复制
function sum(a,b){
    console.log(a,b)
}
sum.call(null,1,2);
sum.apply(null,[1,2])
sum.bind(null,1,2)

打印结果如下:

只打印了两次,为什么sum.bind(null,1,2)没有执行呢?咱们将代码修改一下:

代码语言:javascript
复制
function sum(a,b){
    console.log(a,b)
}
sum.call(null,1,2);
sum.apply(null,[1,2])
let fn = sum.bind(null,1,2)
fn()

打印结果如下:

函数调用bind方法之后返回了一个函数,这个函数必须手动调用一下。

有得时候我们只想改变函数的this值并不想当时就调用,bind方法会更合适。还有就是bind向函数传递参数也是逐个传递的,这点类似call。

以上便是call apply bind的具体用法了,你有没有比着代码敲一下呢?赶紧打开电脑测试验证一下吧。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-02-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 nodejs全栈开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档