JavaScript继承方式详解

JavaScript实现继承的方式主要有两种: 原型链继承和借助构造函数继承

一、原型链继承

原型链继承的主要思想是将父类型的实例赋给子类型的原型,这样子类型就可以通过原型对象的[[prototype]]访问到父类型的所有属性和方法。具体实现方式如下:

function SuperType()
{
    this.property = true;        //SuperType 实例属性 property
}
SuperType.prototype.getSuperValue = function()
{
    return this.property;        //SuperType 方法 getSuperValue()
}
function SubType()
{
    this.subProperty = false;    //SubType 实例属性 subProperty
};
SubType.prototype = new SuperType();    //将SuperType实例赋给SubType的原型
SubType.prototype.constructor = SubType;
SubType.prototype.getSubValue = function()
{
    return this.subProperty;            //SubType 添加方法 getSubValue()
};
 
var instance = new SubType();
alert(instance.getSuperValue());    // true

父类型SuperType的实例中有一个内部指针[[prototype]]指向SuperType的原型,而将这个实例赋值给子类型SubType的原型后,instance在搜索属性时,会先搜索自身的属性,然后搜索它的原型SubType.prototype中的属性,包括SuperType的实例属性和后添加自身的原型属性,然后会继续搜索到SuperType.prototype的属性。这样SubType就可以访问到SuperType的全部属性了。也就是实现了继承。这个继承是通过在它们之间建立原型链实现的。

不过原型链继承有一些问题。首先,子类型不能像父类型传递参数,其次,由于父类型的实例属性都变成了子类型的原型属性,那么那些引用类型的属性值就会在子类型的所有实例中共享,这样往往跟我们预期的效果不同。

二、借助构造函数继承

相对于原型中引用类型共用的问题,构造函数就有自己的突出优势,这在之前讲解创建对象方法时也提到过。借助构造函数继承的思想是在子类构造函数中调用父类构造函数。具体实现方法如下:

function SuperType(name)
{
    this.name = name;
    this.friends = ["Mike", "John"];
}
function SubType()
{
    // 调用SuperType构造函数,并为其传递一个参数,设置了SubType的name和friends属性值
    SuperType.call(this, "Nicholas");
    //为SubType添加属性age 
    this.age = "22";
}
 
var instance1 = new SubType();
alert(instance1.name);           // Nicholas
instance1.friends.push("Kate"); 
alert(instance1.friends);        // Mike,John,Kate
alert(instance1.age);            // 22
 
var instance2 = new SuperType("Jake");
alert(instance2.friends);        // Mike,John
alert(instance2.name);           // Jake

在SubType的构造函数中通过call()方法调用SuperType的构造函数,这样所有SubType的实例都会有一个firends副本,不存在共用的问题。并且可以在调用SuperType构造函数时传入参数。

当然这种方法的缺点也是显而易见的,它无法实现函数的复用。

三、混入式继承

   function Dog (){
        this.name = "旺财";
        this.age = 0.5;
    }
    var obj = {
        run : function(){
            console.log("跑....");
        },
        eat : function(){
            console.log("吃饱了才有里气跑");
        }
    }
    //混入式继承
    // for(var key in obj){
    //     Dog.prototype[key] = obj[key];
    // }
    var d1 = new Dog();
    d1.eat(); //  吃饱了才有里气跑

四、原型式继承

基本想法:借助原型可以基于已有的对象创建新对象,同时还不必须因此创建自定义的类型。

 function Dog (){
        this.name = "旺财";
        this.age = 0.5;
    }
    var obj = {
        run : function(){
            console.log("跑....");
        },
        eat : function(){
            console.log("吃饱了才有里气跑");
        }
    }
 //直接原型替换
    Dog.prototype = obj;
    var d1 = new Dog();
    var d2 = new Dog();
   // d1.eat(); // 吃饱了才有力气跑...
   // d2.eat(); // 吃饱了才有力气跑...

五、寄生组合式继承

我们首先要知道这两次调用父类的构造函数的真正目的是什么。第一次调用,将父类的实例赋值给子类的实例,我们本质上需要的只有指向父类原型的指针[[prototype]]而已,它使父类和子类通过原型链连接起来,而父类的实例属性我们并不需要,它的继承是通过第二次在子类的构造函数中调用实现的。所以,我们现在只要能想出一个方法,能够获得指向父类原型的指针,并把它添加到子类的原型上,就可以省掉第一次调用了。

道格拉斯•克罗克福德在2006年提出了原型式继承方法,在其中用到了这样一个函数:

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

在这个函数中,首先创建了一个临时的空的构造函数F,然后将参数o赋给F的原型,最后返回一个F的实例。如果把这个函数用在继承的实现中,并将父类的原型对象作为参数传入,就正好满足我们之前的要求:F的原型中保存了父类原型对象的副本,可以将F赋给子类的原型,那么子类就可以访问到父类所有的原型属性了。这个过程可以用下面这个函数包装起来:

function inheritPrototype(subType, superType) {
    var proto = object(superType.prototype);
    proto.constructor = subType;
    subType.prototype = proto;
}

在函数内部,先创建一个父类的原型副本proto, 然后为其添加constructor属性,最后将这个副本赋给子类。这样就可以不通过调用父类的构造函数建立原型链。用这个函数代替之前组合继承方式中的为子类原型赋值的语句就可以了。

function SuperType(name)
{
    this.name = name;
    this.friends = ["Mike","John"];
}
SuperType.prototype.sayName = function()
{
    alert(this.name);
};
function SubType(name,age)
{
    SuperType.call(this, name);    
    this.age = age;                
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function()
{
    alert(this.age);
};

这种寄生组合式继承是目前性能最好的继承方式。

六:经典继承

        // 命名空间
        var itcast={
            create:function (obj){
        //能力检测
                if(Object.create){
                    //es5中 Object.create(); 是一个静态方法
                    // var obj=Object.create(原型对象);
                    // es5中的新语法 ,有兼容新问题
                    return Object.create(obj);
                }else{
                    function F(){};
                    F.prototype=obj;
                    return new F();
                }
            }
        }

            var data={
            name:'赵四',
            age:18
        }


      var d1=itcast.create(data);
      console.log(d1.name) // 赵四
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,176评论 5 469
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,190评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,232评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,953评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,879评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,177评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,626评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,295评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,436评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,365评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,414评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,096评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,685评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,771评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,987评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,438评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,032评论 2 341

推荐阅读更多精彩内容