在一些框架使用中经常会遇到一些诸如
class,extends,super,constructor等关键字或方法,这些都的原理与实现是怎样的呢
- ES5 继承方法
- ES6 的类
- ES6 类的继承
- 模拟类的现
ES5 继承方法
原型链继承
function Parent(){
this.name = 'Nick'
}
Parent.prototype.getName = function(){
console.log(this.name);
}
function Child (){
}
Child.prototype = new Parent()
var child1 = new Child()
console.log(child1.getName()) //Nick
问题(1)包含引用类型值的原型属性会被所有实例共享 (2)创建子类型Child实例时无法传递参数给Parent
借用构造函数继承(在子类构造函数内部调用超类型构造函数【经典继承】
1.避免了引用类型属性被所有实例共享
funcion Parent(){
this.colors = ['red','blue','green']
}
function Child(){
Parent.call(this)
}
var child1 = new Child()
child1.colors.push('black')
child1.colors //'red','blue','green' ,'black'
var child2 = new Child()
child2.colors //'red','blue','green'
2.可以传递参数
funcion Parent(name){
this.name = name
}
function Child(name){
Parent.call(name)
}
var child1 = new Child('kevin');
console.log(child1.name); // kevin
var child2 = new Child('daisy');
console.log(child2.name); // daisy
问题:方法都在构造函数中定义,每次创建实例都会创建一遍方法
组合继承(经典继承+构造函数)
function Parent (name){
this.name = name
this.colors = ['red','blue','green'];
}
Parent.prototype.getName = function (){
console.log(this.name)
}
function Child (name,age){
Parent.call(this,name)
this.age = age
}
Child.prototype = new Parent()
Child.prototype.getAge = function (){
console.log(this.age)
}
var child1 = new Child('nick',12)
child1.colors.push('black');
console.log(child1.colors);
child1.getName();
child1.getAge();child1;
融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式。
问题 会调用两次父构造函数 (1) Parent.call(this,name)(2)Child.prototype = new Parent()
原型式继承
先创建一个临时性构造函数。然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的新实例
function object(o){
function F(){}
F.prototype = o
return new F()
}
// 用此方法得到的新对象其属性通过hasOwnProperty方法可看到是存在新对象的原型上的而不是在新创建的对象上
var person = {
name:'Nich',
friends:['tysd','dfsd','3432']
}
var person1 = object(person);
person1.name = 'Gert';
person1.friends.push('Ron');
var person2 = object(person)
person2.name = 'Linad'
person2.friends.push('Ioios');
问题:包含引用类型的属性值会被共享
寄生式继承
创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象。
function createObj (o) {
var clone = Object.create(o);
clone.sayName = function () {
console.log('hi');
}
return clone;
}
跟借用构造函数模式一样,每次创建对象都会创建一遍方法。
寄生组合式继承
组合继承的问题在于会调用两次父构造函数
function Parent (name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
Parent.prototype.getName = function () {
console.log(this.name)
}
function Child (name, age) {
Parent.call(this, name);
this.age = age;
}
// 关键的三步
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
var child1 = new Child('kevin', '18');
console.log(child1);
即:
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function prototype(child, parent) {
var prototype = object(parent.prototype);
prototype.constructor = child;
child.prototype = prototype;
}