理解 this 是如何动态解析的、原型链是如何工作的,以及类到底给对象模型带来了什么。
在 Kodokon 中打开本课this 的值是在调用点决定的,而不是在声明时决定的。四条规则,按优先级从高到低排列:用 new 调用、显式绑定(call、apply、bind)、作为方法调用(obj.fn()),以及普通调用(fn()),后者在严格模式下会得到 undefined。最常见的现实 bug 由此直接产生:把一个方法从其对象上提取出来,会破坏隐式绑定。
const user = {
name: "Ada",
greet() {
return "Hello, " + this.name;
},
};
console.log(user.greet()); // "Hello, Ada"
const detached = user.greet;
// detached(); // TypeError: this is undefined
const bound = user.greet.bind(user);
console.log(bound()); // "Hello, Ada"箭头函数没有自己的 this:它们像闭包一样,从外层作用域按词法捕获 this。这使它们非常适合用作回调,但用作对象字面量上的方法则适得其反,因为那样 this 会指向外层作用域。在底层,每个对象都通过其原型链进行委托:一个缺失的属性会沿着链条逐环查找,直到到达 null。
function Animal(name) {
this.name = name;
}
Animal.prototype.describe = function () {
return this.name + " is an animal";
};
const dog = new Animal("Rex");
console.log(dog.describe()); // "Rex is an animal"
console.log(Object.getPrototypeOf(dog) ===
Animal.prototype); // true
console.log(dog.hasOwnProperty("describe")); // falseclass 语法并不改变这个模型:它只是让模型更易读。在类体中声明的方法会落到 Constructor.prototype 上,因此是共享的。实例字段(包括作为字段赋值的箭头函数)则会每个实例各自重建一份:this 绑定得到保证,但内存开销成倍增加。最后,#private 字段提供了由引擎强制执行的私有性,这与 _下划线 约定不同。
class BankAccount {
#balance = 0;
deposit(amount) {
if (amount <= 0) throw new Error("Invalid amount");
this.#balance += amount;
return this;
}
get balance() {
return this.#balance;
}
}
const account = new BankAccount();
account.deposit(50).deposit(25);
console.log(account.balance); // 75fn() 时,this 是什么?this 而言,箭头函数有什么特别之处?