Javascript: call(), apply() and bind()

2/4/2020


Image

this 是上下文执行环境(execution context)的一个属性。函数调用时,会自动与特定的对象绑定。

函数对象: 函数对象

if(this.isEmpty()) {
    var deleteBtn = document.createElement("button");
    deleteBtn.innerHTML = "Empty Cart";
    deleteBtn.className = "delete";

    var myCart = this;
    // when calling method on deleteBtn, 'this' becomes deleteBtn and we lose the context of myCart
    // this is why we save a reference to myCart as 'this'
    deleteBtn.addEventListener("click", function() {
        myCart.clearCart();
    });
    cartDOM.appendChild(deleteBtn);
}

有时候我们需要保存this, 因为deleteBtn.addEventListener中this指向的是deleteBtn对象.使用call()、apply()、bind()可以解决这个问题。

bind()

bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。

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()、apply() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。两者唯一的不同在于传参的形式不一样。 可以参考下面的例子。

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