您的位置:首页 > Web前端 > JavaScript

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

2016-12-26 20:32 681 查看
众所周知,JavaScript中是没有传统类的概念的

它利用原型链完成继承

对于当时刚学JavaScript的我来说,一时不好接受

声明的方式看起来非常奇怪

不过在我们的ES6中借鉴了很多语言的语法(Python、Java…)

这其中包括class类的概念

class不是新结构而是原型链的语法糖

早在ES4的时候,草案中就已经出现了class

不过ES4由于过于激进,和一系列问题

被大家抵制

不过大家现在完全不用担心ES6步ES4的后尘

(好奇的同学可以看看“传说”中的ES4草案:传送门

类定义

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

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


下面再看看这个新的一等公民是怎样定义的

学习过C++或者Java的同学一定会感觉无比亲切

上面的代码利用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


新的class写法让对象原型更加清晰

更像面向对象的编程语言

不过还是要注意

虽然是模仿传统的继承方式

但是只是语法糖

仍然使用的是[[prototype]]的委托机制

(包括后面谈到的继承,子类不会像其他语言一样拷贝父类的东西)

注意事项

这里需要注意的有

定义类方法前面没有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()); //报错


ES6中类的相关知识就总结到这里了

==主页传送门==
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息