一、call
每个函数都有 call
方法,call 可以改变函数当前的 this 环境(对象)
,记住这点很重要。
例子1:给对象换新欢
const Jack = {
hisGirlName: 'Candy',
getMyGirlFriend() {
console.log(this.hisGirlName)
}
}
const John = {
hisGirlName: 'Lili',
}
Jack.getMyGirlFriend.call(John) // 打印:Lili
例子2:偷天换日的感觉真是太棒了
function Jack() {}
Jack.prototype.bankAccount = '100'
Jack.prototype.getMyMoney = function() {
console.log('Money:', this.bankAccount)
}
function Linda() {}
Linda.prototype.bankAccount = '100W';
const superPerson = new Jack()
console.log(superPerson.getMyMoney()) // 打印:100
console.log(superPerson.getMyMoney.call(new Linda)) // 打印:100W
二、apply
每个函数都有 apply
方法,它与 call
的作用是一模一样的,唯一的区别是,它的传参要用数组形式。
例子1:简化获取列表中的最值方式
const nums = [22,33,2,14,10,100]
const maxNum = Math.max.apply(null, nums)
const minNum = Math.min.apply(null, nums)
console.log(maxNum, minNum) // 打印:100 2
提示:
apply
第二个参数虽是数组形式,但函数接受时是以单个参数形式
,理清这点是有必要的,这也是 Math.max 能够识别“数组”参数的原因。
例子2:给对象换新欢
和 call 一样,这里就不举例了。
三、bind
每个函数都有 bind
方法,它与前面的 call/apply
不同,它并不会立即调用函数,而是返回一个新的函数(通常也叫偏函数)并绑定调用时的传递的 this 执行环境
记住这点很重要。
例子1:先存起来,下次再用
for (var i = 0; i < 5; i ++) {
var self = this
setTimeout(function(num) {
console.log(num)
}.bind(self, i), 1000)
}
// 打印:0 1 2 3 4
解释:bind 绑定了当前所属环境,这里的 i 是按值传参,于是,bind 每次绑定的值便是 i 当前的那个值。当每个定时器执行后将读取当前所处环境的参数值。
利用传参是按值传递的特性,上面的代码也可以改成这样的:
for (var i = 0; i < 5; i ++) {
var fn = function(num) { return function() { console.log(num) } }
setTimeout(fn(i), 1000)
}
四、留意
call/applybind
传递指向环境非this
而是null
时,此时 null ===windows
全局环境。call/apply/bind
可以混合使用。