1,首先理解严格和非严格模式下的全局this
function f1() { console.log(this)}
function f2() { 'use strict' console.log(this)}
f1() // window
f2() // undefined
/**
* 这里因为将foo.fn赋值给f3之后,f3是在全局环境中执行
*/
const foo = {
bar: '10',
fn: function() {
console.log(this)
console.log(this.bar)
}
}
var f3 = foo.fn
f3() // window undefined
/*,
* 如果直接调用的话,此时 this指向最后调用它的对象foo
*/
foo.fn() // { bar: 10, fn: f} 10
2 this 的上下文调用
const o1 = {
text: 'o1',
fn: function() {
return this.text
}
}
const o2 = {
text: 'o2',
fn: function() {
var fn = o1.fn
return fn()
}
}
console.log(o2.fn()) // undefined
/*
* o1.fn进行赋值之后调用,此时 this指向window
*/
3, 构造函数 和this
function foo() {
this.user = 'mike';
const o = {}
return o
}
const ins = new foo();
console.log(ins.user) // undefined
function foo1() {
this.user = 'mike';
return 1;
}
const ins1 = new foo1();
console.log(ins1.user) // mike
/* 如果构造函数中显示的返回一个值,且返回的是一个对象(复杂类型),this指向这个返回的对象;
如果返回的不是对象(基本类型),this指向实例
*/
4,箭头函数,this指向由外层作用域决定
// 如果将箭头函数换成一个匿名函数,this在匿名函数中,指向window
const foo = {
fn: function() {
setTimeout(() => {
console.log(this)
})
}
}
console.log(foo.fn()) // {fn:f}
var a = 123
const foo = () => a => console.log(this)
const obj1 = { a: 2}
const obj2 = { a: 3}
var bar = foo.call(obj1)
console.log(bar.call(obj2)) // 123
/* 由于箭头函数的this绑定无法修改,所以call无法修改,绑定在window下
这里如果把 var变量声明换成const ,将会输出 undefined;因为const声明的变量不会挂载在window上
*/
5,优先级
new 绑定 > 显示bind绑定(call, apply)> 根据调用关系的隐式绑定
6, 总结规律
- 在函数体中,非显式或隐式地简单调用函数时,严格模式下,函数内的this会绑定到undefined上,非严格模式下会被绑定到全局对象window / global上;
- 一般用new方法构造函数时,构造函数内的this会被绑定到新创建的对象上;
- 一般通过call/ apply / bind方法显式调用函数时,函数体内的this会被绑定到指定参数的对象上;
- 一般通过上下文对象调用函数时,函数体内的this会被绑定到该对象上
- 箭头函数中,this的指向由外层(函数/全局)作用域来决定