一直以来有这么个疑问? 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.
在这个例子中:
- MyClass 是一个类,其中包含三个方法:greet、sayGoodbye 和 afterGoodbye。
- myInstance 是 MyClass 的一个实例,初始化时 name 属性被设置为 'Alice'。
- greet 方法正常调用时会输出 Hello, my name is Alice,因为 this 指向 myInstance。
- 当我们将 greet 方法提取到类之外并直接调用时,this 不再指向 myInstance,而是指向全局对象(在非严格模式下)或 undefined(在严格模式下),因此输出 Hello, my name is undefined。
- 使用 bind 方法手动绑定 this 到 myInstance 后,再次调用 greet 方法,this 指向 myInstance,输出 Hello, my name is Alice。
- sayGoodbye 方法在类内部调用 afterGoodbye 方法时,this 正常指向 myInstance,因此输出 Goodbye, Alice! After goodbye, Alice is still here.。
- 当我们将 sayGoodbye 方法提取到类之外并直接调用时,this 不再指向 myInstance,导致 this.name 输出 undefined,并且 this.afterGoodbye 不是一个函数,抛出 TypeError。
- 使用 bind 方法手动绑定 this 到 myInstance 后,再次调用 sayGoodbye 方法,this 指向 myInstance,输出 Goodbye, Alice! After goodbye, Alice is still here.。
通过这个例子,你可以看到手动绑定 this 的重要性,特别是在将方法提取到类之外调用时。