学习前提

理解函数、对象属性和作用域;不要求先学类继承。

本课完成后你能做什么

理解方法的接收者和共享原型,选择简单数据对象或类组织状态。

先理解机制

对象属性查找先检查自身,再沿原型链查找,直到null。class提供声明构造器和原型方法的语法,并没有改变JavaScript的原型模型。实例状态应初始化在构造器中,方法通常共享在原型上。

调用obj.method()时普通方法的this指向obj;把方法取出独立调用可能丢失接收者。bind创建绑定函数,箭头回调也可以显式从外层引用实例。不要依赖事件监听器提供的this来指代业务对象。

继承适合稳定的“是一种”关系,组合常更容易拆分变化。课程记录通常只需普通对象;当多个实例共享行为和状态规则时,类才更有价值。不要为每个JSON字段都包装一层类。

可运行示例

class Progress {
  constructor(total) { this.total = total; this.done = 0; }
  complete() { this.done = Math.min(this.total, this.done + 1); }
  percent() { return this.total === 0 ? 0 : Math.round(this.done / this.total * 100); }
}
const html = new Progress(8);
const css = new Progress(8);
const completeHTML = html.complete.bind(html);
completeHTML();
console.log(html.percent(), css.percent());
console.log(html.complete === css.complete);

推演与验证

结果13、0、true。两个实例的done独立,但complete方法来自共同原型。移除bind后在严格模式独立调用,会因this不存在而失败;通过html.complete()调用则有正确接收者。

常见错误与边界

示例假定total是非负整数,生产入口必须验证。对象展开不保留实例原型方法。JSON解析出来的是普通数据,不能直接调用原实例方法;应验证数据后显式重建状态。

动手练习

构造器拒绝负数、非整数和字符串total;增加undo但不允许done低于0。

参考解法与理由

Number.isInteger加范围检查,失败抛TypeError。undo使用Math.max。总数为0时百分比定义为0,避免NaN。

进一步阅读