两者的区别是.call()接受一组参数,例如myFunction.call(thisValue, 'value1', 'value2')。而.apply()接受的一组参数必须是一个类似数组的对象,例如myFunction.apply(thisValue, ['value1', 'value2'])。
5.1. 隐式调用中的this
在隐式调用.call()或.apply()中,this是第一个参数很明显,在隐式调用中,this作为第一个参数传递给.call()或.apply()。
var rabbit = { name: 'White Rabbit' }; function concatName(string) { console.log(this === rabbit); // => true return string + this.name; } concatName.call(rabbit, 'Hello '); // => 'Hello White Rabbit' concatName.apply(rabbit, ['Bye ']); // => 'Bye White Rabbit'
当应该使用特定上下文执行函数时,隐式调用非常有用。例如为了解决方法调用时,this总是window或严格模式下的undefined的上下文问题。隐式调用可以用于模拟在一个对象上调用某个方法。
function Runner(name) { console.log(this instanceof Rabbit); // => true this.name = name; } function Rabbit(name, countLegs) { console.log(this instanceof Rabbit); // => true Runner.call(this, name); this.countLegs = countLegs; } const myRabbit = new Rabbit('White Rabbit', 4); myRabbit; // { name: 'White Rabbit', countLegs: 4 }
Rabbit中的Runner.call(this, name)隐式调用了父类的函数来初始化这个对象。
6. 绑定函数
绑定函数是与对象连接的函数。通常使用.bind()方法从原始函数创建。原始函数和绑定函数共享相同的代码和作用域,但执行时上下文不同。
方法 myFunc.bind(thisArg[, arg1[, arg2[, ...]]])接受第一个参数thisArg作为绑定函数执行时的上下文,并且它接受一组可选的参数 arg1, arg2, ...作为被调用函数的参数。它返回一个绑定了thisArg的新函数。
function multiply(number) { 'use strict'; return this * number; } const double = multiply.bind(2); double(3); // => 6 double(10); // => 20
bind(2)返回一个新的函数对象double,double 绑定了数字2。multiply和double具有相同的代码和作用域。
与.apply()和.call() 方法相反,它不会立即调用该函数,.bind()方法只返回一个新函数,在之后被调用,只是this已经被提前设置好了。
6.1. 绑定函数中的this
在调用绑定函数时,this是.bind()的第一个参数。.bind()的作用是创建一个新函数,调用该函数时,将上下文作为传递给.bind()的第一个参数。它是一种强大的技术,使咱们可以创建一个定义了this值的函数。
来看看,如何在如何在绑定函数设置 this
const numbers = { array: [3, 5, 10], getNumbers: function() { return this.array; } }; const boundGetNumbers = numbers.getNumbers.bind(numbers); boundGetNumbers(); // => [3, 5, 10] // Extract method from object const simpleGetNumbers = numbers.getNumbers; simpleGetNumbers(); // => undefined (严格模式下报错)
numbers.getNumbers.bind(numbers)返回绑定numbers对象boundGetNumbers函数。boundGetNumbers()调用时的this是number对象,并能够返回正确的数组对象。
可以将函数numbers.getNumbers提取到变量simpleGetNumbers中而不进行绑定。在之后的函数调用中simpleGetNumbers()的this是window(严格模式下为undefined),不是number对象。在这个情况下,simpleGetNumbers()不会正确返回数组。
6.2 紧密的上下文绑定
.bind()创建一个永久的上下文链接,并始终保持它。 一个绑定函数不能通过.call()或者.apply()来改变它的上下文,甚至是再次绑定也不会有什么作用。
只有绑定函数的构造函数调用才能更改已经绑定的上下文,但是很不推荐的做法(构造函数调用必须使用常规的非绑定函数)。
下面示例创建一个绑定函数,然后尝试更改其已预先定义好的上下文
function getThis() { 'use strict'; return this; } const one = getThis.bind(1); // 绑定函数调用 one(); // => 1 // 使用带有.apply()和.call()的绑定函数 one.call(2); // => 1 one.apply(2); // => 1 // 再次绑定 one.bind(2)(); // => 1 // 以构造函数的形式调用绑定函数 new one(); // => Object
只有new one()改变了绑定函数的上下文,其他方式的调用中this总是等于1。
7. 箭头函数
箭头函数用于以更短的形式声明函数,并在词法上绑定上下文。它可以这样使用