一、基础
在ES6之前,主要靠构造函数和原型链的灵活使用实现继承;而在ES6中引入了class(类)的概念,使得继承更加方便,也更接近传统的面向对象语言(C++,Java)中继承的实现。
ES6中类的定义如下:
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ',' + this.y + ')';
}
}
//测试用例
var point = new Point(2, 3);
console.log(point.toString());//(2,3)
console.log(point.hasOwnProperty('x'));//true
console.log(point.hasOwnProperty('y'));//true
console.log(point.hasOwnProperty('toString'));//false
console.log(point.__proto__.hasOwnProperty('toString'));//true
以上代码定义了一个‘类’,里边有一个constructor方法,这就是构造方法,this关键字代表实例对象。ES5中的构造函数Point,对应ES6中Point类的构造方法;
constructor方法是类的默认方法,一个类必须有这个方法(如果没有显示定义,会默认添加constructor方法),通过new命令生成对象实例时,自动调用该方法;
从以上的测试用例也可以看到:实例的属性除非显示定义在其本身(即:this对象上),否则都定义在原型上(这一特性和ES5一致);
constructor方法是类的默认方法,一个类必须有这个方法(如果没有显示定义,会默认添加constructor方法),通过new命令生成对象实例时,自动调用该方法;
从以上的测试用例也可以看到:实例的属性除非显示定义在其本身(即:this对象上),否则都定义在原型上(这一特性和ES5一致);
二、Class的继承
基本用法:Class之间可以通过extends关键字实现继承,这比ES5通过修改原型链实现继承,要方便很多。
示例程序如下:
示例程序如下:
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);
this.color = color;
}
toString() {
return this.color + ' ' + super.toString()
}
}
var p = new ColorPoint(2, 3, 'red');
console.log(p.toString());// red (2,3)
以上代码中,constructor方法和toString方法中,都出现了super关键字,这里表示父类的构造函数,用来新建父类的this对象
注意:
1、子类必须在constructor方法中调用super方法,否则新建实例会报错(因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行再加工,如果不调用super方法,子类就得不到this对象);
2、在子类的构造函数中,只有调用super之后才能用this关键字,否则会报错。原因参考1;
注意:
1、子类必须在constructor方法中调用super方法,否则新建实例会报错(因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行再加工,如果不调用super方法,子类就得不到this对象);
2、在子类的构造函数中,只有调用super之后才能用this关键字,否则会报错。原因参考1;
类的prototype属性和__proto__属性
在ES5中,每个对象都有__proto__属性,指向构造函数的prototype属性。Class作为构造函数的语法糖,同时具有prototype属性和__proto__属性,所以存在两条继承链。
1、子类的__proto__属性,表示构造函数的继承,总指向父类。
2、子类的的prototype属性的__proto__属性,表示方法的继承,总指向父类的prototype属性。
验证如下:
class A {
}
class B extends A {
}
console.log(B.__proto__ === A);//true
console.log(B.prototype.__proto__ === A.prototype);//true