this
this是一个指针,this指向是在函数被调用时确定的,且在函数执行过程中this一旦确认无法更改。 一句话说明this执行: this 的指向,是在调⽤函数时根据执⾏上下⽂所动态确定的。
this绑定规则
- new 绑定
- 显式绑定(call\apply\bind)
- 隐式绑定
- 默认绑定
this绑定优先级
new > 显式 > 隐式 > 默认
默认绑定
当无法应用其他规则时使用默认绑定,通常为函数独立调用。在严格模式下this指向undefined,undefined没有this故报错,在非严格模式下指向全局对象window。
function sayHi(){
console.log('Hello,', this.name);
}
var name = 'YvetteLau';
sayHi(); // Hello,YvetteLau
function sayHi(){
console.log('Hello,', this.name);
}
var person = {
name: 'YvetteLau',
sayHi: sayHi
}
var name = 'Wiliam';
var Hi = person.sayHi;
Hi(); //Hello,Wiliam 此时是独立调用者,指向window,而不是隐式绑定
隐式绑定
当函数调用者被对象所拥有this则指向该对象
function sayHi(){
console.log('Hello,', this.name);
}
var person = {
name: 'YvetteLau',
sayHi: sayHi
}
var name = 'Wiliam';
person.sayHi(); // Hello YvetteLau
对象属性链中只有最后一层会影响到调用位置
function sayHi(){
console.log('Hello,', this.name);
}
var person2 = {
name: 'Christina',
sayHi: sayHi
}
var person1 = {
name: 'YvetteLau',
friend: person2
}
person1.friend.sayHi(); // Hello Christina
// 这题于上题的区别是虽然两者都是作为对象属性方法进行调用,一个属性值为对象另一个为对象中的属性方法,如果是属性方法则指向原先的对象,而是对象则指向该对象
var x = 10;
var obj = {
x: 20,
f: function(){ console.log(this.x); }
};
var bar = obj.f;
var obj2 = {
x: 30,
f: obj.f
}
obj.f(); // 20
bar(); // 10
obj2.f();// 30
//注意点:对象的{}没有作用域,所以属性值中的this指向全局
var name = 'shy'
var a = {
name: this.name
}
注意隐式绑定this丢失问题:回调函数...
显式绑定
call\apply\bind的第一个参数就是this指向的对象
function sayHi(){
console.log('Hello,', this.name);
}
var person = {
name: 'YvetteLau',
sayHi: sayHi
}
var name = 'Wiliam';
var Hi = person.sayHi;
Hi.call(person); //Hi.apply(person) Hello, YvetteLau
当第一个参数为undefined或者null时,this绑定采用默认绑定
var foo = {
name: 'Selina'
}
var name = 'Chirs';
function bar() {
console.log(this.name);
}
bar.call(null); //Chirs
new绑定
函数可以直接调用也可new调用,当使用new调用时,函数this指向新对象
function sayHi(name){
this.name = name;
}
var Hi = new sayHi('Yevtte');
console.log('Hello,', Hi.name);
使用new操作符调用内部相当于执行了以下操作
- 创建一个空对象
- 为空对象添加__proto__属性并指向其构造函数的prototype属性(原型对象)
- 执行构造函数中的代码(为这个新对象添加属性)
- 对构造函数返回值作判断,如果构造函数中没有返回值则返回之前创建的对象;如果构造函数有返回值且返回值是基础数据类型则忽略,是引用类型则返回该引用类型对象。
箭头函数this
箭头函数没有自己的this,它继承于自己外层第一个非箭头函数父级的this
如何准确判断this指向
- 函数是否在new中调用(new绑定),如果是,那么this绑定的是新创建的对象。
- 函数是否通过call,apply调用,或者使用了bind(即硬绑定),如果是,那么this绑定的就是指定的对象。
- 函数是否在某个上下文对象中调用(隐式绑定),如果是的话,this绑定的是那个上下文对象。一般是obj.foo()
- 如果以上都不是,那么使用默认绑定。如果在严格模式下,则绑定到undefined,否则绑定到全局对象。
- 如果把null或者undefined作为this的绑定对象传入call、apply或者bind,这些值在调用时会被忽略,实际应用的是默认绑定规则。
- 如果是箭头函数,箭头函数的this继承的是外层代码块的this。