这三个 Function.prototype
中的函数,老熟人了,可以说是经常看见;但把它们弄明白,的确需要花点功夫。
以简单话语总结
这三个函数都可以修改函数执行时的上下文,也就是修改 this
的指向。
call( thisArg, arg1, ..., argN )
apply( thisArg, [argArray]
bind( thisArg, arg1, ... , argN )
上面可以看见,call
第二个参数是参数列表,apply
第二个参数是数组。并且call
和 apply
都是立即执行的。
bind
第二个参数也是参数列表,但是这个是返回一个函数,还需要调用一下才会执行,也就是被动的。
call() 和 apply()
这两个功能都是一样的,就是写法不同。call
的是参数列表,apply
的可以是数组或类数组 (比如arguments
)。
举个例子:
function func(avg1, avg2) {
console.log(avg1, avg2);
}
function apply_func() {
return func.apply(this, arguments);
}
apply_func(1, 2); // 1 2
function call_func() {
return func.call(this, ...arguments);
}
call_func(3, 4); // 3 4
你可以用这两个来实现继承或者另外一些其他技巧,看自己习惯就行,举个继承的例子:
function Parent (name) {
this.name = name;
}
function Child (name) {
Parent.call(this, name);
}
bind()
相比前面两个,这个bind()
就使用的多了,挺多实现都有bind
的身影。
区别前面也说了,使用bind
后还需要自己调用一次,也就是被动的,没有立即执行的。
举个比较常见的例子:
class Person {
constructor(name) {
this.name = name;
}
sayName() {
console.log('sayName', this.name);
}
sayNameDelay() {
setTimeout(function () {
console.log('sayNameDelay', this.name)
}, 1000);
}
}
let p = new Person('Zeekg');
p.sayName(); // sayName Zeekg
p.sayNameDelay(); // sayNameDelay
可以看见setTimeout
里面的name
输出的undefined
。这里使用bind()
:
class Person {
constructor(name) {
this.name = name;
}
sayName() {
console.log('sayName', this.name);
}
sayNameDelay() {
setTimeout(function () {
console.log('sayNameDelay', this.name)
}.bind(this), 1000); // 这里添加了代码
}
}
let p = new Person('Zeekg');
p.sayName(); // sayName, Zeekg
p.sayNameDelay(); // sayNameDelay Zeekg
但其实直接使用setTimeout(()=> {},1000}
箭头函数一样也可以解决。
写在最后
这篇主要是总结,并没有过多解释怎么使用这些函数。
虽然不难,但完全弄明白还是需要花点时间的。
链接:
如有不正确之处,欢迎在评论区中指出