深入理解javascript中bind、apply、call

相信做过一段时间的javascript开发的同学都或多或少用过或者见到过bind、apply、call方法。他们的作用很简单,就是改变执行函数的this指向,如果您对this了解比较模糊,您可以看这一篇博客

作用

首先,我们了解下,改变执行函数的this指向有哪些作用,对我们开发有哪些好处。同样,我们从一个例子开始吧。

const obj = {
    name: '张三',
    age: 18,
    introduction: function() {
        console.log(`my name is ${this.name}, i am ${this.age} years old`)
    }
}

obj.introduction(); //my name is 张三, i am 18 years old

obj.introduction.apply({name: '李四', age: 22}); //my name is 李四, i am 22 years old

例子中,张三有一个introduction可以介绍他的信息,所以当调用obj.introduction()时,可以打印张三的个人信息,后面,我们将obj.introduction()方法绑定在了对象{name: '李四', age: 22}上,从而改变了this指向,最终打印了李四的个人信息。

由此,我们可以看出通过改变this指向,我们可以实现代码复用。

 

异同

了解了改变this指向的作用后,我们发现bind、apply、call都是可以改变this指向,那它们有何不同之处呢,下面我们讨论下。

1. bind

bind方法第一个参数是需要绑定的对象,后面的参数是改变this指向方法的参数,值得注意的是bind方法的返回值仍然是一个方法,我们需要添加一对小括号才能让他执行。请看使用实例。

const obj = {
    name: '张三',
    age: 18,
    introduction: function(sex) {
        console.log(`my name is ${this.name}, i am ${this.age} years old, my sex is ${sex}`)
    }
}

const bindFunc = obj.introduction.bind({name: '王五', age: 21}, 'men');
bindFunc(); //my name is 王五, i am 21 years old, my sex is men

2.  apply

apply方法第一个参数是需要绑定的对象,第二个参数是一个数组,数组中的元素为改变this指向方法的参数,和bind不同的是,此时函数会立即执行。请看实例。

const obj = {
    name: '张三',
    age: 18,
    introduction: function(sex) {
        console.log(`my name is ${this.name}, i am ${this.age} years old, my sex is ${sex}`)
    }
}
obj.introduction.apply({name: '李四', age: 22}, ['men']); //my name is 李四, i am 22 years old, my sex is men

3. call

call方法和apply方法极为相似,方法第一个参数是需要绑定的对象,后面的参数是改变this指向方法的参数,同样,函数也是立即执行。请看实例。

const obj = {
    name: '张三',
    age: 18,
    introduction: function(sex) {
        console.log(`my name is ${this.name}, i am ${this.age} years old, my sex is ${sex}`)
    }
}

obj.introduction.call({name: '周六', age: 19}, 'men'); //my name is 周六, i am 19 years old, my sex is men

 

关于他们的异同,这里总结了一个表格。 

 

 

相信了解他们的用法是一个比较简单的事儿。不过,作为一个励志成为一个更优秀(tutou)的程序yuan,刨根问底是一个优良品质。

下面,我们来分别实现这三个方法。

1. myBind

程序实现

function myBind(ctx, ...rest) {
    const context = ctx || window;
    const _this = this;

    return function() {
        context.fn = _this;
        context.fn(...rest);
        delete context.fn;
    }
}

Function.prototype.myBind = myBind;

2. apply

程序实现

function myApply(ctx, params) {
    const context = ctx || window;

    ctx.fn = this;
    ctx.fn(...params);
    delete ctx.fn;
}

  Function.prototype.myApply = myApply;

3. call

程序实现

function myCall(ctx, ...rest) {
    const context = ctx || window;

    context.fn = this;
    context.fn(rest);
    delete context.fn;
}
Function.prototype.myCall = myCall;

 

相信上面的代码聪明的你一眼就看懂了。bind、call、apply三个方法的实现原理都是一样的,只是让我们可以通过不同的方式使用它。

他们改变this指向的原理是通过 将需要改变this指向的方法附加在对象中执行,则方法中的this就会指向附加的对象。(在方法中,this 表示该方法所属的对象。)

 

浅陋见识,不足之处,请大神指正。

posted @ 2020-11-17 21:33  一生舍给一座山  阅读(182)  评论(0编辑  收藏  举报