想弄懂this的指向其实并不难,只需要记住最核心的一句话: 谁 '调用'我 , this就指向谁,说人话: this相当于中文中的'我',谁说出来这个字,这个字就代表谁
下面列举几种情况:
1.普通函数this指向window
function fn(){
console.log(this)
}
//(1)普通函数
fn()// this->window 这里其实是window.fn() 此处window可以省略不写
2.对象函数调用 谁调用'我','我'就指向谁
let obj = {
name: "月月",
fn: function () {
console.log(this) // obj
}
}
obj.fn() //this -> obj
3.构造函数 this指向new创建的实例对象
function fn() {
console.log(this)
}
//(2)构造函数
new fn()//this->new创建的实例
4.事件绑定的方法, 此时this指向事件源
<body>
<button>按钮</button>
<script>
document.querySelector('button').addEventListener('click', function () {
console.log(this); // this -> button
})
</script>
</body>
补充一点:箭头函数,在箭头函数里面是没有this的,因为箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this
最后再来说说修改函数内部this的 call() 和 apply() 和 bind()
let obj = {
name: "月月"
}
function fn(a, b) {
console.log(this)
console.log(a + b)
}
fn(10, 20) //this -> window 30
//(1) 函数名.call(修改的this,参数1,参数2………)
fn.call(obj, 10, 20) // this -> obj a+b = 30
//(2) 函数名.apply(修改的this, 数组/伪数组 )
// apply会自动遍历数组和伪数组,然后逐一传参
fn.apply(obj, [20, 30]) // this -> obj a+b = 50
//(3) 函数名.bind(修改的this)
// bind不会立即执行函数,而是得到一个修改this之后的新函数
let newFn = fn.bind(obj) // this -> obj a+b = 100
newFn(50, 50)
关于call和apply和bind三者的区别
1.相同点: 都可以修改this指向
2.不同点:
(1)传参的方式不同:call是单个传参,apply是数组/伪数组传参
(2)执行的机制不同:call和apply会立即执行函数,bind不会立即执行而是得到this的新函数