五种情况分析
this 执行主体,是谁把它执行的【与在哪创建&在哪执行都没有必然的关系】
函数执行
- 看方法前面有没有 “ 点 ” ,没有 “ 点 ” 的情况下,this 是 window 调用【严格模式下是 undefined】
- 有 “ 点 ” 情况下, “ 点 ” 前面是谁 this 指向谁
const fn = function fn() {
console.log(this);
}
let obj = {
name: 'obj',
fn: fn
}
fn() // window
obj.fn() // obj
绑定方法
- 给当前元素的某个事件行为绑定方法,当事件行为触发,方法中的 this 是当前元素本身
document.body.addEventListener('click', function() {
console.log(this); // body
})
注意:给 body 一个宽高,否则不输出~
当前类的实例
- 构造函数体中的 this 就是当前类的实例
function Demo() {
this.name = '这';
this.age = 18;
console.log(this); // Demo
}
let D = new Demo;
箭头函数
- 箭头函数中没有执行主体,this 是所处上下文中的 this
let Demo = {
name: 'DEMO',
fn() {
console.log(this); // Demo
setTimeout(function(){ // 普通函数
console.log(this); // window
},1000)
setTimeout(() => { // 箭头函数
console.log(this); // Demo
},1000)
}
}
Demo.fn()
修改指向
call
- fn 函数基于__proto__找到 Function.prototype.call 把 call 方法执行
- call 方法执行的时候 把 fn 中的 this 改为 Demo
- 把接收的值当作实参传递给 fn 函数
- 并且让 fn 函数立即执行
function fn(x, y) {
console.log(this, x, y); // Demo 10 20
}
let Demo = {
name: 'DEMO'
}
fn.call(Demo, 10, 20)
apply
- apply 总体上和 call 差不多,apply 传实参的时候,要求以数组的形式传递,所以只有两个参数
- 两者只有语法上的区别
function fn(x, y) {
console.log(this, x, y); // Demo 10 20
}
let Demo = {
name: 'DEMO'
}
fn.apply(Demo, [10, 20])
bind
- 和 call / apply 的区别:并没有把 fn 立即执行
- 把传递进来的 Demo / 10 / 20等信息存储起来
- 执行 bind 返回一个新的函数
function fn(x, y) {
console.log(this, x, y); // Demo 10 20
}
let Demo = {
name: 'DEMO'
}
document.body.addEventListener('click', fn.bind(Demo, 10, 20))
总结
- 谁调用指向谁