理解 this
对象的属性可能是一个函数,当引擎遇到对象属性是函数的情况,会将函数单独保存在堆中,然后再将函数的地址赋值给对象属性;而 Javascript 是允许在函数体内引用当前环境的其他变量,那么问题来了,函数可以在不同的运行环境执行。
所以我们就需要一种机制,能够在函数内获得当前运行环境,由此诞生了 this,它的设计目的就是指向函数运行时所在的环境。
this 指向
1. 默认绑定
在非严格模式下,this 指向全局对象(window、global)
var name = '小豪';
function foo() {
console.log(this.name);
}
foo(); // 小豪
2. 隐式绑定
当函数作为对象的属性存在,通过对象属性执行函数时,隐式绑定规则会将 this 绑定到对象上
var name = 'JavaScript';
var obj = {
name: '小豪',
foo() {
console.log(this.name);
},
};
var obj1 = obj.foo;
obj.foo(); // '小豪'
obj1(); // 'JavaScript'
3. 显式绑定
如果 call、apple、bind 的绑定对象是 null 或者 undefined,那么实际上在调用时这些值都会被忽略,所以使用的是默认绑定规则
var name = '10';
var obj = {
name: '100',
};
var obj1 = {
name: '1000',
};
function foo() {
console.log(this.name);
}
foo.call(); // '10'
foo.call(obj); // '100'
foo.call(obj).call(obj1); // '100' 多次调用call方法,以第一次为准 谷歌下测试会报错~
foo.call(obj1).call(obj); // '1000' 多次调用call方法,以第一次为准 谷歌下测试会报错~
4. 通过 new 绑定
指向 new 出来的对象
var name = '10';
function foo(name) {
this.name = name;
}
var obj = {
name: '100',
foo: new foo('1000'),
};
console.log(obj.foo.name); // '1000'
5. ES6 箭头函数绑定
根据它外层(函数/全局)作用域来决定
function foo() {
return () => {
console.log(this.name);
};
}
var name = '1';
var obj = {
name: '10',
};
var obj1 = {
name: '100',
};
var foo1 = foo();
var foo2 = foo.call(obj);
foo1(); // 1
foo2(); // 10
foo2.call(obj1); // 10 箭头函数的 this 绑定后无法被修改
绑定优先级
- new 绑定
- 显示绑定
- 隐式绑定
- 默认绑定