# this, call 和 apply
this 关键字和其他语言最大的区别是,他总是指向一个对象。并且在函数运行时基于当前函数的执行环境动态绑定的。
var obj = {
num: 1,
count() {
console.log(this)
return this.num;
}
}
obj.count() // 1
// 由于执行环境不同,this 指向了 widnow
var count = obj.count
count() // undefined
但是在严格模式下 'use strict' this 的指向又会变为 undefined。这就是 this 丢失。
;(function() {
console.log(this); // window
})();
;(function() {
'use strict'
console.log(this); // undefined 严格模式
})();
call 和 apply 这两个函数都是用来修改函数的 this 指向。他们都属于 Function 对象,这说明每个函数都有这两方法可以调用。
当函数调用了 call 和 apply 时,都会立刻执行这个函数。
call 和 apply 的第一个参数都是 this,第二个参数有所不同:
var f = function(age, work) {
console.log(`我叫:${this.name}, 今年 ${age} 岁, 职业: ${work}`)
}
let o = {
name: '石兴龙'
}
// 我叫:石兴龙, 今年 18 岁, 职业: web前端开发者
f.call(o, 18, 'web前端开发者')
// 我叫:石兴龙, 今年 18 岁, 职业: web前端开发者
f.apply(o, [18, 'web前端开发者'])
// 我叫:石兴龙, 今年 18 岁, 职业: web前端开发者
f = f.bind(o, 18, 'web前端开发者')
// 我叫:石兴龙, 今年 18 岁, 职业: web前端开发者
f();
# call 和 apply 的区别
call 和 apply 都是非常常用的方法。区别在于传入参数的形式不同。
call 第一个是 this 的指向,的第二个之后的参数是函数的参数列表,一般用于参数不确定的函数
apply 接受两个参数。第一个是this的指向,第二个是一个数组,这个数字将被当做被调用的函数的参数列表
在刚刚的例子中,我们还看到了 bind 函数。这其实是 call 的变种。bind 接受参数的方式和 call 是一样的。唯一的区别是他并不会立即执行,而是返回一个已经被修改过 this 的函数。我们可以来尝试手动实现一个 bind 函数。
Function.prototype.bind = function(o) {
var self = this
var bindArgs = arguments
return function() {
var args = []
for (var i = 1; i < bindArgs.length; i++) {
args.push(bindArgs[i])
}
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i])
}
return self.apply(o, args)
}
}
f = f.bind(o, 18, 'web前端开发者')
f();