类声明以class关键字开始,其后是类的名称;剩余部分的语法看起来像对象字面量中的方法简写,并且在方法之间不需要使用逗号。
- class Person {
- //等价于prototype的构造器
- constructor(name) {
- this.name = name;
- }
- SayName() {
- console.log(this.name);
- }
- }
- let per = new Person("cf");
- per.SayName(); //cf
- console.log(typeof Person); //function
构造器最大的用处就是在创建对象时执行初始化,当创建一个对象时,系统会为这个对象的实例进行默认的初始化。如果想改变这种默认的初始化,就可以通过自定义构造器来实现。
类与函数有相似之处,即它们都有两种形式:声明与表达式
- let PersonClass = class {
- constructor(name) {
- this.name = name;
- }
- SayName() {
- console.log(this.name);
- }
- }
- let per = new PersonClass("cc");
- per.SayName();
类表达式和类声明都不会被提升
- let PersonClass = class PersonClass2 {
- constructor(name) {
- this.name = name;
- }
- SayName() {
- console.log(this.name);
- console.log(PersonClass2);
- }
- }
- let per = new PersonClass("cc");
- per.SayName();
此例中的类表达式被命名为PersonClass2.PersonClass2只在类定义内部存在,因此只能用在类方法内部。
在编程中,能被当做值来使用的就成为一级公民,意味着他能作为参数,能作为函数返回值,能用来给变量赋值。js的函数就是一级公民。
- let createObject = function(classDef) {
- return new classDef();
- }
- let obj = new createObject(class {
- SayHi() {
- console.log("hi");
- }
- })
- obj.SayHi();
自有属性需要在类构造器中创建,而类还允许你在原型上定义访问器属性。为了创建一个getter ,要使用 get 关键字,并要与后方标识符之间留出空格;创建 setter 用相同方式,只是要换用 set 关键字
- class CustomhtmlElement {
- constructor(element) {
- this.element = element;
- }
- get html() {
- return this.element.innerHTML;
- }
- set html(value) {
- this.element.innerHTML = value;
- }
- }
类方法与类访问器属性也能使用需计算的名称。语法相同于对象字面量中的需计算名称:无须使用标识符,而是用方括号来包裹一个表达式
- let methodName = "SayName";
- class PersonClass {
- constructor(name) {
- this.name = name;
- }
- [methodName]() {
- console.log(this.name);
- }
- }
- let per = new PersonClass("cc");
- per.SayName();
可以使用Symbol.iterator来定义生成器方法,从而定义出类的默认迭代器。
- class Collection {
- constructor() {
- this.items = [];
- }
- * [Symbol.iterator]() {
- yield this.items;
- }
- }
- let collection = new Collection();
- collection.items.push(1);
- collection.items.push(2);
- collection.items.push(3);
- for (let num of collection.items) {
- console.log(num);
- }
静态成员不能通过实例来访问,你始终需要直接用类自身来访问
- class PersonClass {
- constructor(name) {
- this.name = name;
- }
- SayName() {
- console.log(this.name);
- }
- static create() {
- return new PersonClass(name);
- }
- }
- let per = new PersonClass.create("cc");
- class Rectangle {
- constructor(length, width) {
- this.length = length;
- this.width = width;
- }
- getArea() {
- return this.length * this.width;
- }
- }
- class Square extends Rectangle {
- constructor(length) {
- super(length, length);
- }
- }
- let sq = new Square(10);
- console.log(sq.getArea()); //100
继承了其他类的类被称为派生类。如果派生类指定了构造器,就需要使用super(),否则就会出错。如果不定义构造器,super()方法会被自动调用,并会使用创建新实例时提供的所有参数。例如:
- class Square extends Rectangle {
- }
- let sq = new Square(10, 10);
- console.log(sq.getArea());//100
使用super需要牢记以下几点
派生类中的方法总是会屏蔽基类的同名方法。例如:你可以将getArea()方法添加到Square类,以便重新定义它的功能。
- class Rectangle {
- constructor(length, width) {
- this.length = length;
- this.width = width;
- }
- getArea() {
- return this.length * this.width;
- }
- }
- class Square extends Rectangle {
- constructor(length, name) {
- super(length, length);
- this.name = name;
- }
- getArea() {
- return `this is ${this.name} input ${this.length}`
- }
- }
你也可以使用super.getArea()方法来调用基类中的同名方法
- class Square extends Rectangle {
- constructor(length) {
- super(length, length);
- }
- getArea() {
- return super.getArea();
- }
- }
如果基类包含静态成员,那么这些静态成员在派生类中也是可用的。
- class Rectangle {
- constructor(length, width) {
- this.length = length;
- this.width = width;
- }
- getArea() {
- return this.length * this.width;
- }
- static create(length, width) {
- return new Rectangle(length, width);
- }
- }
- class Square extends Rectangle {
- constructor(length) {
- super(length, length);
- }
- }
- let sqr = Square.create(10, 10);
- console.log(sqr.getArea()); //100
在ES6中派生类的最强大能力,或许就是能够从表达式中派生类。只要一个表达式能够返回一个具有[[Constructor]]属性以及原型的函数,你就可以对其使用extends。
- function Rectangle(length, width) {
- this.length = length;
- this.width = width;
- }
- Rectangle.prototype.getArea = function() {
- return this.length * this.width;
- }
- class Square extends Rectangle {
- constructor(length) {
- super(length, length);
- }
- }
- let x = new Square(10);
- console.log(x.getArea()); //100
extends后面能接受任意类型的表达式,这带来了巨大的可能性,例如动态的决定要继承的类。
- function Rectangle(length, width) {
- this.length = length;
- this.width = width;
- }
- Rectangle.prototype.getArea = function() {
- return this.length * this.width;
- }
- function getBase() {
- return Rectangle;
- }
- class Square extends getBase() {
- constructor(length) {
- super(length, length);
- }
- }
- let x = new Square(10);
- console.log(x.getArea());
任意表达式都能在extends关键字后使用,但并非所有表达式的结果都是一个有效的类。
在ES6类的继承中,this的值会先被基类创建,随后才被派生类的构造器所修改。结果是this初始就拥有作为基类的内置对象的所有功能,并能正确的接收与之关联的所有功能。
- class MyArray extends Array {
- }
- let arr = new MyArray();
- arr[0] = 'red';
- console.log(arr.length);
- arr.length = 0;
- console.log(arr[0]);
继承内置对象的一个有趣方面是:任意能返回内置对象实例的方法,在派生类上却会自动返回派生类的实例。
- class MyArray extends Array {
- }
- let arr = new MyArray(1, 2, 3);
- let subitems = arr.slice(1, 2);
- console.log(subitems);
来源: http://www.cnblogs.com/xzsty/p/7976929.html