call, apply, bind 的用法

103 阅读2分钟

call

使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。(call() 方法接受的是一个参数列表)

function.call(thisArg, arg1, arg2, ...)    // thisArg为要传的this值,没有时用undefined或null占位
  1. 使用 call 方法调用父构造函数
function Product(name, price) {  
    this.name = name;  
    this.price = price;  
}

function Food(name, price) {  
    Product.call(this, name, price);  
    this.category = 'food';  
}

function Toy(name, price) {  
    Product.call(this, name, price);  
    this.category = 'toy';  
}

var cheese = new Food('feta', 5);  
var fun = new Toy('robot', 40);

  1. 使用 call 方法调用匿名函数

var animals = [  
{species: 'Lion', name: 'King'},  
{species: 'Whale', name: 'Fail'}  
];

for(var i = 0; i < animals.length; i++){  
(function(i){  
this.print = function(){  
console.log('#' + i + ' ' + this.species + ': ' + this.name);  
}  
this.print();  
}).call(animals[i], i); //call调用匿名函数  
}

  1. 使用 call 方法调用函数并且指定上下文的 'this'

var obj = {  
animal: 'cats', sleepDuration: '12 and 16 hours'  
};

function greet(){  
var reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ');  
console.log(reply);  
}

greet.call(obj); //"cats typically sleep between 12 and 16 hours"

  1. 使用 call 方法调用函数并且不指定第一个参数(argument)

var sData = 'marshall';

function display(){  
console.log("sData's value is %s",this.sData);  
}

display.call(); // sData value is marshall

在严格模式下,this 的值将会是undefined


var sData = 'marshall';

function display(){  
console.log("sData's value is %s",this.sData);  
}

display.call(); // Cannot read the property of 'sData' of undefined

apply

调用一个具有给定 this 值的函数,以及以一个数组(或一个类数组对象)的形式提供的参数。 (apply() 方法接受的是一个包含多个参数的数组。)


apply(thisArg, argsArray) // thisArg为this的值, argsArray为数组或类数组对象

  1. 使用apply和内置函数 对于一些需要写循环以遍历数组各项的需求,我们可以用apply完成以避免循环。

//找出数组中最大值和最小值  
var numbers = [5, 6, 2, 3, 7];  
//使用Math.min和Math.max以及apply函数时的代码  
var max = Math.max.apply(null, numbers);  
var min = Math.min.apply(null, numbers);

上边这种调用apply的方法,有超出JavaScript引擎参数长度上限的风险。 如果我们的参数数组非常大,推荐使用下边这种混合策略:将数组切块后循环传入目标方法


function minOfArray(arr) {  
    var min = Infinity;  
    var QUANTUM = 32768;

    for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
        var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len)));
        min = Math.min(submin, min);
    }

    return min;

}

var min = minOfArray([5, 6, 2, 3, 7]);

bind

bind()函数会创建一个新的绑定函数,这个绑定函数包装了原函数的对象。调用绑定函数通常会执行包装函数。 使用 bind 可以让 this 不被改变


function f1(p1, p2){  
console.log(this, p1, p2)  
}  
let f2 = f1.bind({name:'frank'}) // f2 就是 f1 绑定了 this 之后的新函数  
f2() // 等价于 f1.call({name:'frank'})

bind 还可以绑定其他参数


let f3 = f1.bind({name:'frank'}, 'hi')  
f3() // 等价于 f1.call({name:'frank'}, hi)