JS 从建立之初就不支持类,也没有把类继承做为定义类似对象以及关联对象的主要方式,这让很多开发者感到困惑。而从 ES1 诞生以前直到ES5 时期,不少库都建立了一些工具,让 JS 显得貌似能支持类。尽管一些 JS 开发者强烈认为这门语言不须要类,但为处理类而建立的代码库如此之多,致使 ES6 最终引入了类。es6
JS 在 ES5 及更早版本中都不存在类。与类最接近的是:建立一个构造器,而后将方法指派到
该构造器的原型上。这种方式一般被称为建立一个自定义类型。例如:编程
function PersonType(name) { this.name = name; } PersonType.prototype.sayName = function() { console.log(this.name); }; let person = new PersonType("Nicholas"); person.sayName(); // 输出 "Nicholas" console.log(person instanceof PersonType); // true console.log(person instanceof Object); // true
此代码中的 PersonType 是一个构造器函数,并建立了单个属性 name 。 sayName() 方法被
指派到原型上,所以在 PersonType 对象的全部实例上都共享了此方法。接下来,使用 new
运算符建立了 PersonType 的一个新实例 person ,此对象会被认为是一个经过原型继承了
PersonType 与 Object 的实例。
这种基本模式在许多对类进行模拟的 JS 库中都存在,而这也是 ES6 类的出发点。函数
类声明以 class 关键字开始,其后是类的名称;剩余部分的语法看起来就像对象字面量中的
方法简写,而且在方法之间不须要使用逗号。做为范例,此处有个简单的类声明:工具
class PersonClass { // 等价于 PersonType 构造器 constructor(name) { this.name = name; } // 等价于 PersonType.prototype.sayName sayName() { console.log(this.name); } } let person = new PersonClass("Nicholas"); person.sayName(); // 输出 "Nicholas" console.log(person instanceof PersonClass); // true console.log(person instanceof Object); // true console.log(typeof PersonClass); // "function" console.log(typeof PersonClass.prototype.sayName); // "function"
es6中类关键字class本质是一种语法糖,而使用类实现的继承其本质上就是原型的继承.学习
在编程中,能被看成值来使用的就称为一级公民( first-class citizen ),意味着它能做为参
数传给函数、能做为函数返回值、能用来给变量赋值。 JS的函数就是一级公民(它们有时又
被称为一级函数),此特性让 JS 独一无二
ES6 延续了传统,让类一样成为一级公民。这就使得类能够被多种方式所使用。例如,它能
做为参数传入函数:this
function createObject(classDef) { return new classDef(); } let obj = createObject(class { sayHi() { console.log("Hi!"); } }); obj.sayHi(); // "Hi!
ES6 以前,实现自定义类型的继承是个繁琐的过程。严格的继承要求有多个步骤。例如,研
究如下范例:prototype
function Rectangle(length, width) { this.length = length; this.width = width; } Rectangle.prototype.getArea = function() { return this.length * this.width; }; function Square(length) { Rectangle.call(this, length, length); } Square.prototype = Object.create(Rectangle.prototype, { constructor: { value:Square, enumerable: true, writable: true, configurable: true } }); var square = new Square(3); console.log(square.getArea()); // 9 console.log(square instanceof Square); // true console.log(square instanceof Rectangle); // true
Square 继承了 Rectangle ,为此它必须使用 Rectangle.prototype 所建立的一个新对象来
重写 Square.prototype ,而且还要调用 Rectangle.call() 方法。这些步骤经常会搞晕 JS
的新手,并会成为有经验开发者出错的根源之一。code
类让继承工做变得更轻易,使用熟悉的 extends 关键字来指定当前类所须要继承的函数,即
可。生成的类的原型会被自动调整,而你还能调用 super() 方法来访问基类的构造器。此处
是与上个例子等价的 ES6 代码:对象
class Rectangle { constructor(length, width) { this.length = length; this.width = width; } getArea() { return this.length * this.width; } } class Square extends Rectangle { constructor(length) { // 与 Rectangle.call(this, length, length) 相同 super(length, length); } } var square = new Square(3); console.log(square.getArea()); // 9 console.log(square instanceof Square); // true console.log(square instanceof Rectangle); // true
ES6 的类让 JS 中的继承变得更简单,所以对于你已从其余语言学习到的类知识,你无须将其
丢弃。 ES6 的类起初是做为 ES5 传统继承模型的语法糖,但添加了许多特性来减小错误。继承