ECMAScript6(ES6)标准之class类的定义、继承及静态方法

1 类定义

我们先来看看我们一般的原型链方法

function Person(name, age){
    this.name = name;
    this.age = age;
}
Person.prototype.say = function(){
    console.log('my name is ' + this.name + ', ' + this.age + ' years old');
}
var person  = new Person('payen', '19');
person.say(); //my name is payen, 19 years old

上面的代码利用ES6的class这样写

class Person {
    constructor(name, age){
        this.name = name;
        this.age = age;
    }
    say(){
        console.log('my name is ' + this.name + ', ' + this.age + ' years old');
    }
}
var person = new Person('payen', '19');
person.say(); //my name is payen, 19 years old

注意事项

这里需要注意的有

  • 定义类方法前面没有function关键字
  • 方法之间不能加“,”逗号
  • 类没有提升行为
  • 类内部定义方法不可枚举

函数是有提升行为的 
所以下面的写法没有问题

foo();
function foo(){
    ...
}

但是类没有 
下面的写法浏览器就会报错

var person = new Person();  //错误
class Person{
    ...
}

类内部定义的方法是不可枚举的 
我们可以用for-in验证

for(var prop in person){
    console.log(prop);
}

我们发现传统原型链打印了name,age,say 
但是使用class方法只打印了name,age

类表达式

类的另一种定义方式就是类表达式 
上面的代码也可以这样写

var demo = class {
    constructor(name, age){
        this.name = name;
        this.age = age;
    }
    say(){
        console.log('my name is ' + this.name + ', ' + this.age + ' years old');
    }
}
console.log(demo);
var person  = new demo('payen', '19');   <-- 注意
person.say(); //my name is payen, 19 years old

类比于我们的函数表达式 
以及函数的name属性

function demo(){};
console.log(demo.name); //demo

var demo = function(){};
console.log(demo.name); //demo

var demo = function foo(){};
console.log(demo.name); //foo

class demo{}
console.log(demo.name); //demo

let demo = class {};
console.log(demo.name); //demo

let demo = class foo{};
console.log(demo.name); //foo

类继承

类之间的继承可以通过extends关键字实现 
先定义一个父类

class Point{
    constructor(x, y){
        this.x = x;
        this.y = y;
    }
    toString(){
        return '点坐标: ' + this.x + ',' + this.y;
    }
}
let fp = new Point(12, 34);
console.log(fp.toString()); //"点坐标: 12,34"

接着是子类的声明

class ColoredPoint extends Point{
    constructor(x, y, color){
        super(x, y);
        this.color = color;
    }
    toString(){
        return this.color + super.toString();
    }
}
let sp = new ColoredPoint(56, 78, '红色');
console.log(sp.toString()); //"红色点坐标: 56,78"

这个子类的构造函数中出现了一个新的关键字super 
没有它的话,就无法继承父类的实例属性 
(子类中有constructor,内部就要有super) 
(子类没有自己的this对象,需要继承父类的this对象再添加东西) 
super指代父类的实例(父类的this对象) 
这里的super(x,y)就是调用父类的构造函数 
super.toString()就是调用父类toString()方法
 

换成我们ES5的继承大概是这个样子的

function ColoredPoint(x, y) {
    Point.apply(this, [x, y]);
}
ColoredPoint.prototype = Object.create(Point.prototype, {
    toString: function() {
        ...
    }
});
ColoredPoint.prototype.constructor = ColoredPoint;

ES5的继承, 
实质是先创造子类的实例对象this 
然后再将父类的方法添加到this上面(Parent.apply(this))

ES6的继承, 
实质是先创造父类的实例对象this(必须先调用super) 
然后再用子类的构造函数修改this

它们的实现机制是不同的

静态方法

类相当于实例中的原型 
所有类中定义的方法都会被实例继承 
如果在类方法前加上static 
就不会被实例继承,而是直接通过类来调用

class Foo{
    static print(){
        return 'hello world';
    }
}
console.log(Foo.print()); //"hello world"

静态方法也可以从super调用 
子类调用父类的static方法也只能在静态函数中调用

class Bar extends Foo{
    static say(){
        return super.print();
    }
}
let b = new Bar();
console.log(Bar.print()); //"hello world"
console.log(Bar.say()); //"hello world"
console.log(b.say()); //报错
    class Point {
        constructor(x,y) {
            this.x = x;
            this.y = y;
        }
        toString() {
            return this.x + "==" + this.y
        }
    }

    class ColorPoint extends Point {
        constructor(x,y,color) {
            super(x,y)
        }
        hi() {
            return super.toString();
        }
    }
    // console.log(Object.getPrototypeOf(ColorPoint) === Point); // true
    //Object.getPrototypeOf方法可以用来从子类上获取父类。因此,可以使用这个方法判断,一个类是否继承了另一个类。

 

https://blog.csdn.net/q1056843325/article/details/53862167

 

你可能感兴趣的:(class)