重学JS-7-一图掌握this关键字

2023-04-22 16:17:48 浏览数 (2)

思维导图

通过下面的思维导图,我们先对JavaScript的this关键字有一些基本的了解。

函数的“this”

我们在对象内部,想要访问对象的属性,就会需要用到this。

当然我们也可以直接使用对象变量名,但是变量名可以被重新赋值,直接使用变量名总是不保险的,而且也不方便阅读。

代码语言:javascript复制
let user = {
  name: "John",
  age: 30,

  sayHi() {
    // "this" 指的是“当前的对象”
    alert(this.name);
    // alert(user.name);
  }

};

user.sayHi();

“this”指向调用方法的对象

JS的“this”有更高的灵活性。

我们知道JS的函数,也可以作为对象的属性,一个函数同时可以被赋值给多个对象。

这个时候,函数的this,是指向调用方法的对象。

代码语言:javascript复制
let user = { name: "John" };
let admin = { name: "Admin" };

function sayHi() {
  alert( this.name );
}

// 在两个对象中使用相同的函数
user.f = sayHi;
admin.f = sayHi;

// 这两个调用有不同的 this 值
// 函数内部的 "this" 是“点符号前面”的那个对象
user.f(); // John(this == user)
admin.f(); // Admin(this == admin)

“this”绑定的规则

凭经验去判断this的指向,不太容易,我们可以总结出下面四条绑定规则,用来判断this的指向。

默认绑定

非严格模式下,没有对象时,this会是全局对象(比如浏览器中的window),这就是默认绑定

代码语言:javascript复制
function sayHi(){ 
    console.log("Hi", this); 
} 
sayHi(); // Hi Window

严格模式下,没有对象时,this是undefined。

代码语言:javascript复制
'use strict'; 
function sayHi(){ 
    console.log("Hi", this); 
}
sayHi(); // Hi undefined

隐式绑定

调用对象的方法时,进行隐式绑定,this指向它的调用者。

这是我们最常见也最容易理解的绑定规则。

代码语言:javascript复制
let user = {
  name: "John",
  age: 30,

  sayHi() {
    // "this" 指的是“当前的对象”
    alert(this.name);
    // alert(user.name);
  }

};

user.sayHi();

硬绑定

与隐式绑定相对,我们显式得指定this的对象。

这里我们用到callapplybind

代码语言:javascript复制
let obj1 = {
    name: 'obj1',
    sayHi() {
        // "this" 指的是“当前的对象”
        console.log(this.name);
      }
}; 
let obj2 = {
    name: 'obj2'
}
let obj3 = {
    name: 'obj3'
}

var tmp = obj1.sayHi.bind(obj2)
tmp() // => 'obj2'
obj1.sayHi.call(obj3) // => 'obj3'

构造函数绑定

New绑定,构造函数的this指向对象实例。

代码语言:javascript复制
function Person(){
    console.log('Hi', this);
}
let person = new Person(); // => Hi Person {}

规则优先级

先说结论:显式 or new > 隐式 > 默认

不存在同时使用显示绑定和new绑定的操作。

参考显示绑定时候的例子,可以验证下这个优先级。

代码语言:javascript复制
let obj1 = {
    name: 'obj1',
    sayHi() {
        // "this" 指的是“当前的对象”
        console.log(this.name);
      }
}; 
let obj2 = {
    name: 'obj2'
}
let obj3 = {
    name: 'obj3'
}

var tmp = obj1.sayHi.bind(obj2)
tmp() // => 'obj2'
obj1.sayHi.call(obj3) // => 'obj3'

箭头函数没有this

箭头函数的this,直接指向外层函数的this

所以箭头函数也不能用做构造函数。

代码语言:javascript复制
let user = {
  firstName: "Ilya",
  sayHi() {
    let arrow = () => alert(this.firstName);
    arrow();
  }
};

user.sayHi(); // Ilya

0 人点赞