一文读懂 es6 中class方法中的this绑定

一直以来有这么个疑问? class 的方法中没有自动的绑定this 为什么手动绑定之后,在绑定之后的方法里调用class中的其他的方法(这个方法为什么就能使用this,不也应该是null或者undefined或者window吗) 还是说这就是class的机制?

于是带着这个疑问去寻找答案

在 JavaScript 中,类的方法中的 this 关键字通常会自动绑定到当前实例对象上。然而,当你将一个类的方法提取出来作为独立的函数调用时,this 的绑定就会丢失,变成 undefined(在严格模式下)或全局对象(在非严格模式下),而不是 null。

手动绑定 this 通常使用 bind、call 或 apply 方法来实现。当你手动绑定 this 之后,你实际上是在创建一个新的函数,并且在这个新函数中,this 被固定为你所指定的对象。因此,在绑定之后的方法里调用类中的其他的方法时,this 仍然指向你所绑定的对象,而不是 null。

这是因为当你使用 bind 方法时,bind 会返回一个新的函数,这个新函数中的 this 值会被永久性地绑定到 bind 方法中传入的第一个参数。当你调用这个新函数时,无论是在哪里调用,this 的值都是你绑定的那个对象。

这是 JavaScript 类和对象机制的一部分,确保了在实例方法中调用其他实例方法时,this 能够正确地引用实例对象。如果你在调用方法时不手动绑定 this,而方法是在类之外的地方被调用,那么 this 就不会自动指向类的实例,而是会丢失绑定,这可能会导致 this 指向全局对象或变为 undefined。

因此,手动绑定 this 是为了确保在方法被提取为独立函数之后,依然可以正确地访问类的实例属性和其他方法。
下面是一个简单的例子,展示了如何在类之外的地方调用类的方法,并解释为什么需要手动绑定 this。

复制代码
class MyClass {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }

  sayGoodbye() {
    console.log(`Goodbye, ${this.name}!`);
    this.afterGoodbye();
  }

  afterGoodbye() {
    console.log(`After goodbye, ${this.name} is still here.`);
  }
}

const myInstance = new MyClass('Alice');

// 正常调用类中的方法
myInstance.greet(); // 输出: Hello, my name is Alice

// 将方法提取到类之外并尝试调用
const extractedGreet = myInstance.greet;
extractedGreet(); // 输出: Hello, my name is undefined

// 手动绑定 this 后再调用
const boundGreet = myInstance.greet.bind(myInstance);
boundGreet(); // 输出: Hello, my name is Alice

// 类中的一个方法在类之外调用另一个方法
myInstance.sayGoodbye(); // 输出: Goodbye, Alice! After goodbye, Alice is still here.

// 将另一个方法提取到类之外并尝试调用
const extractedSayGoodbye = myInstance.sayGoodbye;
extractedSayGoodbye(); // 输出: Goodbye, undefined! TypeError: this.afterGoodbye is not a function

// 手动绑定 this 后再调用
const boundSayGoodbye = myInstance.sayGoodbye.bind(myInstance);
boundSayGoodbye(); // 输出: Goodbye, Alice! After goodbye, Alice is still here.

在这个例子中:

  1. MyClass 是一个类,其中包含三个方法:greet、sayGoodbye 和 afterGoodbye。
  2. myInstance 是 MyClass 的一个实例,初始化时 name 属性被设置为 'Alice'。
  3. greet 方法正常调用时会输出 Hello, my name is Alice,因为 this 指向 myInstance。
  4. 当我们将 greet 方法提取到类之外并直接调用时,this 不再指向 myInstance,而是指向全局对象(在非严格模式下)或 undefined(在严格模式下),因此输出 Hello, my name is undefined。
  5. 使用 bind 方法手动绑定 this 到 myInstance 后,再次调用 greet 方法,this 指向 myInstance,输出 Hello, my name is Alice。
  6. sayGoodbye 方法在类内部调用 afterGoodbye 方法时,this 正常指向 myInstance,因此输出 Goodbye, Alice! After goodbye, Alice is still here.。
  7. 当我们将 sayGoodbye 方法提取到类之外并直接调用时,this 不再指向 myInstance,导致 this.name 输出 undefined,并且 this.afterGoodbye 不是一个函数,抛出 TypeError。
  8. 使用 bind 方法手动绑定 this 到 myInstance 后,再次调用 sayGoodbye 方法,this 指向 myInstance,输出 Goodbye, Alice! After goodbye, Alice is still here.。

通过这个例子,你可以看到手动绑定 this 的重要性,特别是在将方法提取到类之外调用时。

相关推荐
哈哈哈hhhhhh7 天前
JavaScript进阶ES6
javascript·es6
Zz_waiting.7 天前
Javaweb - 14.1 - 前端工程化
前端·es6
htt232110 天前
前端记录项目中用到的js
前端·ecmascript·es6
Warren9812 天前
Java异常讲解
java·开发语言·前端·javascript·vue.js·ecmascript·es6
西岭千秋雪_13 天前
前端工程化:ES6特性
前端·javascript·ecmascript·es6
上单带刀不带妹17 天前
ES6中import与export的用法详解
开发语言·javascript·es6·import·export
秉承初心18 天前
Vue3与ES6+的现代化开发实践(AI)
前端·vue.js·es6
渣渣盟20 天前
JavaScript核心概念全解析
开发语言·javascript·es6
xptwop22 天前
05-ES6
前端·javascript·es6
Watermelo61722 天前
Web Worker:让前端飞起来的隐形引擎
前端·javascript·vue.js·数据挖掘·数据分析·node.js·es6