ES2015引入的JavaScript类是否需与原型互操作?实现方式是否受限?
ES2015类与原型系统的强制绑定关系
咱先把话说死:ES2015引入的类必须和JavaScript的原型系统深度互操作,JavaScript实现者根本不能选择完全不兼容原型的实现方式——规范里写得明明白白,类的底层逻辑就是基于原型链的,甚至可以说类是原型继承的语法糖(但比单纯的语法糖多了一些规范约束)。
具体来说,有几个核心强制要求:
- 成员函数必须挂载到类的原型对象上
规范明确规定,类中定义的非静态成员函数,必须被设置为类构造函数的prototype属性的可枚举属性。比如写这么一段代码:
执行后,class User { sayHi() { return `Hi, I'm ${this.name}`; } }User.prototype.sayHi必须指向这个sayHi函数,而且通过new User()创建的实例,其__proto__必然指向User.prototype——你可以自己打印验证:const user = new User(); console.log(user.__proto__ === User.prototype); // 输出 true console.log(User.prototype.sayHi === user.sayHi); // 输出 true - 类继承必须遵循原型链规则
当你用extends实现继承时,规范要求子类的prototype的__proto__必须指向父类的prototype,同时子类构造函数的__proto__指向父类构造函数。这完全就是原型链继承的标准逻辑,所以instanceof、原型方法查找这些特性必须和传统原型代码完全兼容。比如:class Admin extends User {} const admin = new Admin(); console.log(admin instanceof User); // 必须输出 true console.log(admin.sayHi === User.prototype.sayHi); // 必须输出 true - 必须保证新旧代码的互操作性
ES规范的核心原则之一是向后兼容,所以类代码必须能和旧的原型式代码无缝协作。比如你可以给User.prototype手动添加一个方法,所有User类的实例都能直接调用;反过来,类的实例也能被传入依赖原型链的旧函数中,完全不会有问题。
说白了,ES2015的类不是凭空创造了一套新的面向对象模型,而是在现有原型系统上封装了更友好的语法,让习惯类式编程的开发者更容易上手,但底层的运行机制必须严格遵循原型系统的规则——这是规范强制要求的,没有商量的余地。
内容的提问来源于stack exchange,提问作者Aditya
相关产品推荐
相关产品推荐

