在玩完ES6之后,我真的开始喜欢可用的新语法和功能,但是我确实对类有疑问。
新的ES6类只是旧原型模式的语法糖吗?还是幕后还有更多事情要做?即:
class Thing { //... classy stuff doStuff(){} }
vs:
var Thing = function() { // ... setup stuff }; Thing.prototype.doStuff = function() {}; // etc
是的,也许,但是一些语法糖有牙齿。
声明一个类将创建一个函数对象,该函数对象是该类的构造函数,并使用constructor在类主体内提供的代码以及与该类同名的命名类。
constructor
类构造函数具有一个普通的原型对象,类实例以常规的JavaScript方式从该对象继承属性。在类主体中定义的实例方法将添加到此原型中。
ES6没有提供在类体内声明要存储在原型上并继承的类实例默认属性值(即,不是方法的值)的方法。要初始化实例值,可以将它们设置为构造函数内的局部非继承属性,也可以prototype按照与普通构造函数相同的方式,将它们手动添加到类定义之外的类构造函数的对象中。(我不是在争论为JavaScript类设置继承属性的优点或其他问题)。
prototype
在类主体中声明的静态方法将添加为类构造函数的属性。避免使用静态类的方法名称与继承了标准功能属性和方法竞争Function.prototype,例如call,apply或length。
Function.prototype
call
apply
length
不太麻烦的是,类声明和方法始终在严格模式下执行,并且该功能很少引起注意:.prototype类构造函数的属性是只读的:您无法将其设置为为某些特殊功能而创建的其他对象目的。
.prototype
扩展类时会发生一些有趣的事情:
prototype扩展类构造函数的object属性自动在prototype要扩展的类的对象上原型化。这并不是特别新颖,可以使用来复制效果Object.create。
Object.create
扩展类的构造函数(对象)会自动原型化在要扩展的类的构造函数上,而不是Function。尽管使用Object.setPrototypeOf甚至可以复制对普通构造函数的影响childClass.__proto__ = parentClass,但这将是一种非常不寻常的编码实践,并且在JavaScript文档中经常建议不要这样做。
Function
Object.setPrototypeOf
childClass.__proto__ = parentClass
还有其他区别,例如,类对象未按使用function关键字声明的命名函数的方式进行吊起。
function
我认为认为类声明和表达式在所有将来的ECMA Script版本中保持不变不会太天真,并且看看是否以及何时进行开发会很有趣。可以说,将“语法糖”与ES6(ECMA-262标准版本6)中引入的类相关联已经成为一种时尚,但是我个人试图避免重复它。