目录
1 普通函数的this指向
【代码1】
function foo() {
console.log(this) // 没调用者指向window, 严格模式('use strict')下指向 undefined
}
foo()
【代码2】
setTimeout(function () {
console.log(this)
}, 1000)
上述代码可以写成:
window.setTimeout(function () {
console.log(this) // window调用,所以指向window
}, 1000)
【代码3】
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
console.log(this) // btn调用,所以指向 btn
})
【代码4】
const obj = {
name: '张三',
say: function () {
console.log(this)
}
}
obj.say() // obj调用设个函数,所以函数中的this指向obj
总结:对于普通函数:谁调用就指向谁;没有调用者就指向window, 在严格模式下指向undefined
2 箭头函数的this指向
对于箭头函数而言,函数内不存在this,沿用上一级的,上一级没有就继续往上面找,直到找到有this的地方
【适用】:需要使用上层this的地方
【不适用】:构造函数、原型函数、DOM事件函数
3 改变this的指向
3.1 call() 方法改变this指向
【代码】
const obj = {
name: '张三'
}
function f(a, b) {
console.log(this)
console.log(a + b)
}
f(1, 2) // this指向 window
// call() 方法调用函数、改变this指向
f.call(obj, 1, 2)
原本不加call直接调用函数时,this指向window,同过call将this指向obj
3.2 apply() 方法改变this指向
语法:
【代码】注意apply 传递参数使用的是数组的形式
const obj = {
name: '张三'
}
function f(a, b) {
console.log(this)
console.log(a + b)
}
// apply() 方法调用函数、改变this指向
f.apply(obj, [1, 2])
【使用场景】求数组最大值
之前我们使用展开运算符
console.log(Math.max(...arr))
现在使用apply()方法
const arr = [1, 6, 3, 9, 4]
console.log(Math.max.apply(null, arr))
3.3 bind()方法改变this指向
语法:
【代码】注意bind()不会调用函数
const obj = {
name: '张三'
}
function f(a, b) {
console.log(this)
console.log(a + b)
}
// bind() 方法不会调用函数、但能改变this指向
const newF = f.bind(obj, 1, 2) // bind方法就相当于返回一个函数,并且该函数中的this指向是指定的
newF()
【需求】有一个按钮,点击里面就禁用,2秒钟之后开启
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
this.disabled = true
// 在这个普通函数里面改变this指向, 由window改为btn
setTimeout(function () {
this.disabled = false
}.bind(btn), 2000)
})
在这里我们想改变this指向,但是又不想立即调用函数,所以使用bind()方法
上述三个方法总结:
-> 相同点:都可以改变函数内部的this指向
-> 不同点:(1)call 和 apply 会调用函数并且改变函数内部的this指向
(2)call 和 apply 传递的参数不一样, call传递参数 arg1, arg2, ... 形式。而apply必须以数组的形式
(3)bind 不会调用函数,可以改变函数内部的this指向
-> 应用场景:(1)call调用函数并且可以传递参数;
(2)apply 经常跟数组又关系,比如借助于数学对象实现求数组的最大 值和最小值 ;
(3)bind 不调用函数,但是还想改变this指向,比如改变定时器内部的 this指向。