1. Es5
实现继承
1.1 在javascript
中定义类
在Es5
的时代,javascript
是没有class
关键字的,但是javascript
是支持对象的,因此,可以使用function
返回一个对象来定义一个类。
function Person(name, age){
this.name = name;
this.age = age;
this.say = function(){
console.log(`${this.name}: ${this.age}`);
}
}
var person1 = new Person('person1', 1);
person1.say(); // person1: 1
使用上述的代码,我们就使用function
定义了一个简单的Person
类。但是上面的代码写法不够好,一般方法可以通过类的prototype
原型链进行定义,这样更利于扩展。可以将上面代码修改为:
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.say = function () {
console.log(`${this.name}: ${this.age}`);
}
var person1 = new Person('person1', 1);
person1.say(); // person1: 1
1.2 实现继承
现在,我想定义一个Engineer
类,继承自Person
类。
// 第一次尝试
function Person(name, age) {
this.name = name;
this.age = age;
this.say = function () {
console.log(`${this.name}: ${this.age}`);
}
}
function Engineer(name, age, title) {
Person.call(this, name, age);
this.title = title;
this.say = function () {
console.log(`${this.name}(${this.title}): ${this.age}`);
}
}
var person1 = new Person('person1', 1);
person1.say(); // person1: 1
var engineer1 = new Engineer('engineer', 2, 'advanced');
engineer1.say();
console.log(`engineer inherit from Person: ${engineer1 instanceof Person}`);
console.log(`person inherit from Engineer: ${person1 instanceof Engineer}`);
/**
* person1: 1
* engineer(advanced): 2
* engineer inherit from Person: false
* person inherit from Engineer: false
*/
结果已经比较接近了,满足了重载和多态,但是没有满足继承,Engineer
类重载say()
方法成功了,但是,Engineer
不是Person
类的instance
。
原因是因为,Engineer
类没有显示的与Person
类发生关系,只是在Engineer
的原型链中添加了Person
的name
和age
属性,但是本质上,Engineer
类的对象还不是Person
类的实例。所以我们只需要让Engineer
对象是Person
类的实例即可。
// 第二次尝试
function Person(name, age) {
this.name = name;
this.age = age;
this.say = function () {
console.log(`${this.name}: ${this.age}`);
}
}
function Engineer(name, age, title) {
Person.call(this, name, age);
this.title = title;
this.say = function () {
console.log(`${this.name}(${this.title}): ${this.age}`);
}
}
Engineer.prototype = new Person(); // sencond try.
var person1 = new Person('person1', 1);
person1.say(); // person1: 1
var engineer1 = new Engineer('engineer', 2, 'advanced');
engineer1.say();
console.log(`engineer inherit from Person: ${engineer1 instanceof Person}`);
console.log(`person inherit from Engineer: ${person1 instanceof Engineer}`);
/**
* person1: 1
* engineer(advanced): 2
* engineer inherit from Person: true
* person inherit from Engineer: false
*/
可以看到,从结果上看第二次尝试是成功的,加入了Engineer.prototype = new Person
就解决了Engineer
类与Person
累的继承性问题。
2. Es6
实现继承
Es6
中引入了class
与extends
关键字,这是Es6
中的继承写法简单了很多,对于上面的例子,在Es6
中的实现如下:
class Person {
_name = '';
_age = 0;
constructor(name, age) {
this._name = name;
this._age = age;
}
get name() {
return this._name;
}
set name(value) {
this._name = value;
}
get age() {
return this._age;
}
set age(value) {
this._age = value;
}
say = function() {
console.log(`${name}: ${age}`);
}
}
class Engineer extends Person {
_title = '';
constructor(name, age, title) {
super(name, age);
this._title = title;
}
get title() {
return this._title;
}
set title(value) {
this._title = value;
}
say = function () {
console.log(`${this._name} (${this._title}): ${this._age}`);
}
}
var pereson1 = new Person('person1', 1);
var engineer1 = new Engineer('engineer1', 2, 'advanced');
person1.say();
engineer1.say();
console.log(`engineer inherit from Person: ${engineer1 instanceof Person}`);
console.log(`person inherit from Engineer: ${person1 instanceof Engineer}`);
/**
* person1: 1
* engineer(advanced): 2
* engineer inherit from Person: true
* person inherit from Engineer: false
*/
可以看到Es6
的写法简单了很多,省去了很多prototype
的调用。所以在平常工作中可以尽量使用Es6
的语法,或者typescript
。