this绑定规则

142 阅读3分钟

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。

参考链接:juejin.cn/post/684490…