this指向
- 全局作用域中或者普通函数中this指向全局对象window
- 立即执行函数this必定指向window
- 定时器this指向window
- 事件中this指向事件源对象
- 方法中谁调用就指向谁(谁调用,就指向谁)
- 构造函数中this指向对象实例
this绑定规则
默认绑定规则
- 默认绑定全局对象window
console.log(this === window); //true
// Window对象
- 全局作用域下独立调用函数,this指向window
function get() {
console.log(this === window) // true
}
get()
隐式绑定规则
var person = {
name: '张三',
run: function(time) {
console.log(`${this.name}跑了,${time}分钟`);
}
};
// 对象调用
person.run(30)
person.run.call(person, 30)
// 张三跑了,30分钟
var name = 222;
var a = {
name: 111,
say: function () {
console.log(this.name);
}
}
var fun = a.say;
fun(); // fun拿到a.say的引用,然后在全局下独立调用:222
a.say(); // 111
var b = {
name: 333,
say: function(fun) {
fun()
}
}
b.say(fun) // window调用:222
b.say = a.say;
b.say() // 333
记住:父函数有能力决定子函数this的指向,例如forEach里第一个参数是一个函数,第二个参数就是this绑定的对象,不写默认绑定window
显式绑定
call、apply、bind bind返回一个新函数,新函数指向绑定的对象,旧函数不会
call、apply和bind call、apply、bind方法的共同点: call:xxx.call(thisArg, arg1, arg2, ...) apply:xxx.apply(thisArg, argsArray) bind:xxx.call(thisArg, arg1, arg2, ...) call、apply和bind区别:call、apply是先执行,bind是后执行(绑定后需要再次执行)
new绑定
this指向函数实例化之后的对象
绑定规则优先级
new绑定 > 显式绑定 > 隐式绑定 > 默认绑定
箭头函数this指向问题
箭头函数没有自己的this指向,它的this指向上一级作用域的this(最外层代码块) 之前,我们想让内部函数的this指向外部函数的this,我们只能这样:
var a = 0;
function foo() {
let that = this; //指向obj
console.log(this);
function test() {
console.log(that); //指向obj
}
test();
}
let obj = {
a: 1,
foo: foo,
};
obj.foo();
或者使用bind/call/apply显式绑定外部函数的this:
var a = 0;
function foo() {
console.log(this); //指向obj
function test() {
console.log(this);
}
test.call(obj);
}
let obj = {
a: 1,
foo: foo,
};
obj.foo();
箭头函数this指向不遵循上述的四种规则 独立调用对箭头函数无效
var a = 0;
function foo() {
let test = () => {
console.log(this);
};
return test;
}
let obj = {a: 1, foo: foo};
obj.foo()();
// obj.foo()返回test obj.foo()()调用test 而且是独立调用 但是this还是指向obj
隐式绑定对箭头函数无效:
let a = 0;
let obj1 = {
a: 1,
foo: () => {
console.log(this);
},
};
obj1.foo(); //指向window
显式绑定对箭头函数无效:
var a = 0;
function foo() {
let test = () => {
console.log(this);
};
return test;
}
let obj1 = {
a: 1,
foo: foo,
};
let obj2 = {
a: 2,
foo: foo,
};
obj1.foo().call(obj2);
//obj1.foo()返回test obj1.foo.call(obj2)把test的指向绑定到obj2上,无效,this依然指向obj1
/**
* obj1.foo().call(obj2)
* 第一步:obj1.foo()返回test,这时foo()的this指向obj1(普通函数的隐式绑定)
*
* 第二步:test.call(obj2),箭头函数的显式绑定无效,所以箭头函数中的this需要在定义的地方向上层作用域中查找,
* 就找到foo的作用域,即第一步中this的指向obj1
* */
var name = 'name';
var a = {
name: 111,
b: {
name: 222,
say: () => {
console.log(this.name)
}
}
}
a.b.say() // name
class A {
name = 111;
say = () => {
console.log(this.name);
}
}
var b = new A()
b.say(); // 111
var name = 'name';
var a = {
name: 111,
say: function(){
console.log(this.name) // say于name平级, 111
let fn = () => {
console.log(this.name)
};
return fn(); // 111, this指向a
}
}
a.say()