一,原型的继承
javascript中的继承是通过原型链来体现的。先看几句代码
function Foo() {
var f1 = new Foo();
f1.a = 10;
Foo.prototype.a = 100;
Foo.prototype.b = 200;
console.log(f1.a); //10
console.log(f1.b); //200
}
以上代码中,f1是Foo函数new出来的对象,f1.a是f1对象的基本属性,f1.b是怎么来的呢?——从Foo.prototype得来,因为f1.__proto__指向的是Foo.prototype
访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链。
看图:

f1本身没有hasOwnProperty方法,这个hasOwnProperty方法是从Object.prototype中来的

由于所有的对象的原型链都会找到Object.prototype,因此所有的对象都会有Object.prototype的方法。这就是所谓的“继承”。
我们都知道每个函数都有call,apply方法,都有length,arguments,caller等属性。为什么每个函数都有?这肯定是“继承”的。函数由Function函数创建,因此继承的Function.prototype中的方法。
二、Class 的继承
class Person {
constructor(name, age){
this.name = name
this.age = age
}
sayHi(){
console.log('你好,我是'+this.name)
}
}
Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
class PrimaryPerson extends Person{ //=>extends 类似实现原型继承
constructor(name, age) {
super(name); //// 调用父类的constructor(name)。
this.age = age;
}
myName() {
console.log('你好,我叫jack ' + this.age);
}
}
注意PrimaryStudent的定义也是class关键字实现的,而extends则表示原型链对象来自Person。子类的构造函数可能会与父类不太相同,例如,PrimaryPerson需要name和age两个参数,并且需要通过super(name)来调用父类的构造函数,否则父类的name属性无法正常初始化。
PrimaryPerson已经自动获得了父类Person的sayHi方法,我们又在子类中定义了新的myName方法。
ES6引入的class和原有的JavaScript原型继承有什么区别呢?实际上它们没有任何区别,class的作用就是让JavaScript引擎去实现原来需要我们自己编写的原型链代码。简而言之,用class的好处就是极大地简化了原型链代码。
目前,主流浏览器都不支持ES6的class。