javascript如何实现面向对象_prototype和class语法有何不同【教程】

11次阅读

javaScript的prototypeclass本质是同一套原型机制的两种写法,class是语法糖;prototype手动操作易出错因需显式挂载方法、易覆盖原型链、继承需手动设置且无私有支持;class自动处理constructor、extends、Static等,但不提升且混用时易破坏原型链;选择取决于兼容性、控制需求与团队规范。

javascript如何实现面向对象_prototype和class语法有何不同【教程】

javascriptprototypeclass 本质是同一套原型机制的两种写法,class 是语法糖,不是新模型 —— 所以别指望它带来 Java 那种真正的类继承。

prototype 方式怎么写、为什么容易出错

手动操作 prototype 是在直接暴露和修改函数的原型对象,灵活性高但容错低:

  • function Person(name) { this.name = name; } 定义构造函数后,必须显式往 Person.prototype 上挂方法,否则实例无法访问
  • 如果误写成 Person.prototype = { say() { } },会彻底覆盖原有原型(包括 constructor 指针),导致 new Person().__proto__.constructor === Person 失败
  • 多个构造函数间模拟“继承”需手动设置 Child.prototype = Object.create(Parent.prototype),再补 constructor,漏一步就出问题
  • 没有内置的私有字段或方法支持,所有属性都可被外部读写

class 语法到底做了什么封装

class 并不改变原型链行为,只是把常见操作打包成更紧凑、更易读的声明式写法:

  • class 声明自动设为 constructor 方法,且该方法不可枚举(Object.keys(Person.prototype) 看不到)
  • extends 关键字背后调用的是 Object.setPrototypeOf(Child.prototype, Parent.prototype),还确保子类 constructor 正确指向自身
  • static 方法自动挂到构造函数本身(Person.sayHi),而非原型上
  • 但注意:class 声明不会提升(hoisting),必须先定义再使用,否则报 ReferenceError
class Animal {   constructor(name) {     this.name = name;   }   speak() {     return `${this.name} makes a sound`;   }   static isAnimal(obj) {     return obj instanceof Animal;   } }

prototype 和 class 混用时的坑

两者可以共存,但混合修改容易引发预期外行为:

立即学习Java免费学习笔记(深入)”;

  • class Dog extends Animal 定义后,再执行 Dog.prototype.speak = function() { ... } 会覆盖 class 中定义的方法,但不会影响父类原型
  • 若在 class 外部给 Dog.prototype 赋值整个对象(如 Dog.prototype = { ... }),会切断 extends 建立的原型链,instanceof Animal 返回 false
  • class 内部定义的 getter/setter 或方法,其 [[Enumerable]]false;而手动在 prototype 上添加的普通函数默认为 true,这会影响 for...inObject.keys() 的结果

该选哪个:看团队、看环境、看需求

现代项目基本统一用 class,但理解 prototype 仍是调试和阅读旧代码的刚需:

  • 需要兼容 IE 或极老运行时?只能用 prototype + functionclass 在 IE 完全不支持)
  • 写库或框架底层(比如实现自己的 EventEmitter)?直接操作 prototype 更可控,也更轻量
  • 涉及动态方法注入、运行时重写原型逻辑?class 的静态结构反而碍事
  • 多人协作或长期维护?class 的语义更清晰,尤其配合 typescript 后类型推导更稳

真正关键的不是语法选择,而是意识到:无论用哪种写法,obj.__proto__ === Constructor.prototype 这条链始终没变。忘了这点,任何语法糖都会变成陷阱。

text=ZqhQzanResources