ES5中的继承
原理:首先对于属性方面,一般是在子构造函数里面调用父构造函数,通过call改变执行上下文,Father.call(this, name); 完成属性继承。
其次对原型上的方法继承,根据原型的向上查找规则,首先创建一个对象(该对象的__proto__指向父构造函数的原型),然后将该对象赋给子构造函数的原型
Son.prototype=Object.create(Father.prototype);
或者Son.prototype=new Father();
经过上述操作(即连接了图中6操作+7操作+1操作)后,这时的Son.prototype.constcuctor指向的是Father(),而一般原型的constructor指向函数本身,
因此,需要操作Son.prototype.constcuctor=son;(图中2操作)让它重新指向Son()。
1 function Father(name) { 2 this.name = name; 3 } 4 5 function Son(name, age) { 6 Father.call(this, name); 7 this.age = age; 8 } 9 Father.prototype.getName = function() { 10 console.log(this.name); 11 } 12 // 子类的原型是父类的一个实例,可以new一个出来,也可以create一个出来 13 // Son.prototype = new Father; 14 Son.prototype=Object.create(Father.prototype); 15 // 修正构造器,这里注意要修改Son的构造器指向赋值为Son 16 Son.prototype.constructor = Son; 17 //子类自己的方法 18 Son.prototype.getAge = function() { 19 console.log(this.age); 20 } 21 var s1 = new Son(‘李四‘, 222); 22 console.log(s1); // Son {name:‘李四‘,age:22} 23 s1.getName(); // 李四 24 console.log(Son.prototype.constructor); // Son 25 console.log(s1.constructor); // Son 26 s1.getAge(); // 22 27 //HACK:这里通过__proto__这个s1实例的属性找到了Son的prototype,并为其添加了say的方法 28 s1.__proto__.say = function() { 29 console.log(‘hhhhhhhhhhhhhhhhhhhhhhhh‘); 30 } 31 s1.say() // 打印 hhhhhhhhhhhhhhh 32 // NOTE: __proto__这个属性是具体到某个实例化后的对象才有的属性,指向他所属的类的原型 33 console.log(new Son(‘a‘,2).__proto__); // 为Son对象
ES6中的继承
原理:ES6封装了class,extends关键字来实现继承。
子类通过extends继承父类,然后通过在子类中构造函数 super(name); 完成属性继承。注意这句代码需要在构造函数中的第一行。
区别于ES5,这里不再需要修改子类的原型的构造函数指向。
1 class Father { 2 constructor(name) { 3 this.name = name; 4 } 5 getName() { 6 console.log(this.name); 7 } 8 // 这里是父类的f方法 9 f() { 10 console.log(‘fffffffffffffffffffffff‘); 11 } 12 } 13 class Son extends Father { 14 constructor(name, age) { 15 super(name); // HACK: 这里super()要在第一行 16 this.age = age; 17 } 18 getAge() { 19 console.log(this.age); 20 } 21 // 子类的f方法 22 f() { 23 console.log(‘sssssssssssssssssssssss‘); 24 } 25 } 26 var s1 = new Son(‘张一‘, 12); 27 s1.getName(); 28 s1.getAge(); 29 console.log(s1.__proto__.constructor); // 为Son,不用修正 30 s1.f(); // 打印ssssssssssssss