javascript的继承模式

在javascript里面看到javascript的继承模式和传统的继承模式是有区别的,就想查资料看一下到底有区别,就看到了这篇文章,以为讲得还能够,暂时先放上来,之后有别的东西再补充:
http://segmentfault.com/a/1190000000766541javascript

基本模式

var Parent = function(){
    this.name = 'parent';
};
Parent.prototype.getName = function(){
    return this.name;
};
Parent.prototype.obj = {a:1};

var Child = function(){
    this.name = 'child';
}
Child.protytype = new Parent();

var parent = new Parent();
var child = new Child();

console.log(parent.getName());//parent
console.log(child.getName());//child

这种事最简单实现原型继承的方法,直接把父类的对象复制给子类的构造函数的原型,这样子类的对象就能够访问到父类以及父类构造函数的protytype
这里写图片描述
这种方法的优势就是实现起来比较简单,不须要任何特殊的操做;同时他的缺点也很明显,若是子类须要作跟父类构造函数中相同的初始化动做,那么就得在子类构造函数中再重复一遍父类中的操做:php

var Parent = function(name){
    this.name = name || 'parent';
};
Parent.prototype.getName = function(){
    return this.name;
};
Parent.prototype.obj = {a:1};

var Child = function(name) {
    this.name = name || 'child';
};
Child.prototype = new Parent();

var parent = new Parent('myParent');
var child = new Child('myChild');

console.log(parent.getName());//myParent
console.log(child.getName());//myChild

上述还只是初始化name属性,若是初始化工做不断增长,这种方式也不是很方便。java

借用构造函数

var Parent = function(name){
    this.name = name || 'parent';
};
Parent.prototype.getName = function(){
    return this.name;
}
Parent.prototype.obj = {a:1};

var Child = function(name){
    Parent.apply(this,arguments);
}
Child.prototype = new Parent();

var parent = new Parent('myParent');
var child = new Child('myChild');

console.log(parent.getNmae());//myParent
console.log(child.getName());//myChild

上面这种方法在子类构造函数中经过apply调用父类的构造函数进行相同的的初始化工做,这样无论负累作了多少初始化工做,子类能够执行一样的初始化工做。可是上面这种实现方法存在一个问题,父类构造函数被执行了两次,一次是在子类构造函数中,椅子是在赋值子类原型的时候,这是多余的,咱们能够作如下改进:web

var Parent = function(name){
    this.name = name || 'parent';
};
Parent.prototypr.getName = function(){
    return this.name;
};
Parent.prototype.obj = {a:1};

var Child = function(name){
    Parent.apply(this,arguments);
};
Child.protytype = Parent.protytype;

var parent = new Parent('myParent')
var child = new Child('myChild');

console.log(parent.getName());//myParent
console.log(child.getName());//myChild

这样咱们只须要在子类构造函数中执行一次父类的构造函数,同时又能够继承父类原型中的属性,这也比较原型的初衷,就是吧须要复用的内容放在原型中,咱们能够继承原型中可复用的内容
这里写图片描述segmentfault

临时构造函数模式

上面借用构造函数模式仍是存在问题,它把父类的原型直接赋值给子类的原型,这会形成一个问题,就是若是对子类的原型作了修改,那么这个修改同时也会影响到父类的原型,进而影响父类对象。app

var Parent = function(name){
    this.name = name || 'parent';
};
Parent.prototype.getName = function(){
    return this.name;
};
Parent.prototype.obj = {a:1};

var Child = function(name){
    Parent.apply(this,arguments);
};
var F = new function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();

var parent = new Parent('myParent');
var child = new Child('myChild');

console.log(parent.getName());//myParent
console.log(child.getName());/myChild

这样作事在子类原型和父类原型之间加入一个临时的构造函数F,切断了子类原型和父类原型之间的联系,这样子类原型的修改就不会影响到父类原型。svg

继续讨论

上面能够刻到的咱们在Parent的prototype属性中加入一个obj对象字面量属性,可是一直没有使用函数

var Parent = function(name){
    this.name = name || 'parent';
};
Parent.prototype.getName = function(){
    return this.name;
};
Parent.prototype.obj = {a:1};

var Child = function(name){
    Parent.aplly(this,arguments);
};
var F = new function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();

var parent = new Parent('myParent');
var child = new Child('myChild');

console.log(child.obj.a);//1
console.log(parent.obj.a);//1
child.obj.a = 2;
console.log(child.obj.a);//2
console.log(parent.obj.a);//2

在上面这种状况,当咱们把child对象obj.a修改的时候,同时父类的原型中的obj.a也会被修改。缘由是由于当访问child.obj.a的时候,咱们会沿着原型链一直找到父类的prototype中,而后找到了obj属性,而后对obj.a进行修改.this

var Parent = function(name){
    this.name = name || 'parent';
};
Parent.prototype.getName = function(){
    return this.name;
};
Parent.prototype.obj = {a:1};

var Child = function(name){
    Parent.aplly(this,arguments);
};
var F = new function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();

var parent = new Parent('myParent');
var child = new Child('myChild');

console.log(child.obj.a);//1
console.log(parent.obj.a);//1
child.obj.a = 2;
console.log(child.obj.a);//2
console.log(parent.obj.a);//2
相关文章
相关标签/搜索