【译】 JS中 this 的call,apply和bind方法

432 阅读4分钟

译者:江吉仪

原文地址:medium.com/@omergoldbe…

回顾一下“this”

在面向对象的 js中,万物皆对象,因为万物皆对象,我们可以为函数设置和访问额外的属性。

给函数设置额外属性和给函数添加方法是很好...但是我们怎么访问这些属性和方法???

我们介绍过 this 关键字。我们知道到每个函数都会自动获得 this 这个属性。如果我们要为这个函数执行上下文创建一个抽象模型(我不是唯一个这样子做的人...对吧?!?!),他会像这样子的:

img

我们会花了一点时间来熟悉this关键字,但当我们了解this用处,我们会意识到它是多么有用了。this是在函数内部使用的,并且总是引用某个对象——这个对象会在使用“this”的地方调用函数

但事情肯定永远是不完美的,有时候我们会失去this 的指向。当这个事情发生时,我们最后会迷惑的方式保存this 的指向,查看具体例子

为什么要保存 this 的指向?因为deleteBtn.addEventListener的 this 指向的deleteBtn对象。 这样子不太好,我们有更好的的办法吗?

###call(),apply()和 bind() - 新的希望

到现在为止,我们把函数当做一个由名字(同样可以是一个匿名函数)和其调用时执行代码组成的对象,但这不是全部的真相,作为一个热爱真理的人,我有必要让你知道函数实际上看起来是下面这样子的:

![image-20190811170841394](/Users/tongzhirong/Library/Application Support/typora-user-images/image-20190811170841394.png)

这是啥? 别担心!我会通过三个相似的方法添加到函数上面,通过例子让你明白。

bind()

bind()的官方文档:bind()方法创建了一个新的函数,当他被调用时,新函数 this 关键字设置为传递第一个参数(实际上有很多东西可以展开,但时间原因下一次再聊)

这是很强大的,让我们在调用的时候明确的定义 this 的值 ,让我们看下代码:

var pokemon = {

fistname : 'Pika',

lastname: 'Chu',

getPokeName: function() {

var fullname = this.fistname + '' + this.lastname;

return fullname;

}

var pokemonName = function () {

console.log(this.getPokeName()+ 'i choose you ')

}

var logPokemon = pokemonName.bing(pokemon); }

在第 14 行使用 bind 方法。

让我们分解一下代码,当我们使用 bind()方法:

1 js 引擎会创建一个新的 pokemonName 实例,然后绑定 pokemon 作为他的 this 的变量。最重要的是理解它复制 pokemonName 函数了。

2.在创建了 pokemonName 函数副本后,让他去调用 logPokemon()。 尽管它最初不是在 pokemon 对象上面。但现在它将要识别属性(Pika 和Chu)和方法

最棒的事情是,在我们绑定了一个值之后,我们可以像使用普通函数一样使用它,我们甚至可以让函数接受参数,然后传递:

var pokemon = {
    firstname: 'Pika',
    lastname: 'Chu ',
    getPokeName: function() {
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;
    }
};

var pokemonName = function(snack, hobby) {
    console.log(this.getPokeName() + 'I choose you!');
    console.log(this.getPokeName() + ' loves ' + snack + ' and ' + hobby);
};

var logPokemon = pokemonName.bind(pokemon); // creates new object and binds pokemon. 'this' of pokemon === pokemon now

logPokemon('sushi', 'algorithms'); // Pika Chu  loves sushi and algorithms

call(),apply()

call()的官方文档: call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

这就是说,我们可以调用任何函数,并指明具体的 this 指向,有点像 bind()方法。可以把我们从垃圾代码中解放出来。

bind 和 call 方法的区别是call 方法:

1.可以接受别的参数。

2立即执行调用它的函数。

3call 方法不会复制正在调用它的函数。

call 和 apply 的目标都是一样的。他们的区别是 call 期望所有的参数都单独传递,apply 期望是传递一个包含所有参数的数组。例如:

var pokemon = {
    firstname: 'Pika',
    lastname: 'Chu ',
    getPokeName: function() {
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;
    }
};

var pokemonName = function(snack, hobby) {
    console.log(this.getPokeName() + ' loves ' + snack + ' and ' + hobby);
};

pokemonName.call(pokemon,'sushi', 'algorithms'); // Pika Chu  loves sushi and algorithms
pokemonName.apply(pokemon,['sushi', 'algorithms']); // Pika Chu  loves sushi and algorithms

这些内置在函数的方法,每一个都是非常有用的。即使你不在平常写代码中使用,但是当你读别人的代码时候还是会经常遇到。

如果你有任何问题,来 Instagram找我。