继承的方法

1.原型链继承

每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针(constructor),而每个实例都包含一个指向原型对象的内部指针(proto).
实现原型链继承的基本模式:

        //定义第一个类型
        function FirstFun() {
            this.num = 1
        }
        //第一个类型定义方法
        FirstFun.prototype.getFirstNum = function() {
            console.log(this.num);
        }
        //定义第二个类型
        function SecondFun() {
            this.numb = 2
        }
        //继承第一个类型
        SecondFun.prototype = new FirstFun()
        //第二个类型定义方法
        SecondFun.prototype.getSecondNum = function() {
            console.log(this.numb)
        }
        //第二个类型添加实例
        var numbers = new SecondFun()
        //调用实例继承来的方法
        numbers.getFirstNum()
        //结果打印为:1

原型链继承需注意:
(1)别忘记默认原型:
所有函数的默认原型都是object的实例。因此所有默认原型都会包含一个内部指针,指向object.prototype,这也是所有自定义类型都会继承toString()、valueOf()等默认方法的根本原因。
(2)确定原型和实例的方法
第一个:instanceof

alert(numbers instanceof Object)     //true
alert(numbers instanceof FirstFun)   //true
alert(numbers instanceof SecondFun)  //true

第二个:isPrototypeOf()

alert(Object.prototype.isPrototype(numbers))  //true
alert(FirstFun.prototype.isPrototype(numbers))  //true
alert(SecondFun.prototype.isPrototype(numbers))  //true

(3)谨慎定义方法:
给原型添加方法的代码一定要在替换原型的语句之后。
还有,再通过原型链实现继承时,不能使用对象字面量创建原型方法,因为这样会重写原型链。

(4)原型链存在的问题:

第一个问题:
引用类型值的原型属性,会被所有实例共享,这正是为什么要在构造函数中,而不是在原型上定义属性的原因。

        function Obj1() {
            this.colors = ["red","blue","yellow"]
        }

        function Obj2() {
        }

        Obj2.prototype = new Obj1()

        var test1 = new Obj2()
        test1.colors.push("green")
        console.log(test1.colors)  //["red","blue","yellow","green"]

        var test2 = new Obj2
        console.log(test2.colors)  //["red","blue","yellow","green"]

第二个问题:
没办法在不影响所有对象实例的情况下,向超类型的构造函数中传递参数。

2.借用构造函数(有时候也叫伪造对象或者经典继承)

基本思想:在子类型构造函数内部调用超类型构造函数。

函数只不过是在特定环境中执行代码的对象,因此通过使用apply()或者call()方法也可以在(将来)新创建的对象上执行构造函数。

        function Obj1() {
            this.colors = ["red","blue","yellow"]
        }

        function Obj2() {
            Obj1.apply(this)
        }

        var test1 = new Obj2()
        test1.colors.push("green")
        console.log(test1.colors)  //["red","blue","yellow","green"]

        var test2 = new Obj2
        console.log(test2.colors)  //["red","blue","yellow"]
借用构造函数继承优缺点:

(1)优点:可以在子类型构造函数中向超类型构造函数传递参数。

        function Obj1(name) {
            this.name = name
        }

        function Obj2() {
            //继承了Obj1,同时传递了参数
            Obj1.call(this, "Peter")
            this.age = 28
        }

        var test1 = new Obj2()
        console.log(test1.name)  //Peter
        console.log(test1.age)   //28

(2)缺点:方法都在构造函数中定义,因此函数复用就无从谈起。

3.组合继承(也叫伪经典继承)

思路:
通过使用原型链实现対原型属性和方法的继承,通过借用构造函数实现对实例属性的继承。

        function Obj1(name) {
            this.name = name
            this.colors = ['aaa','bbb','ccc']
        }

        Obj1.prototype.sayName = function() {
            console.log(this.name);
        }

        function Obj2(name, age) {
            //继承属性
            Obj1.call(this, name)
            // 添加新的属性
            this.age = age
        }

        //继承方法
        Obj2.prototype = new Obj1()

        //弥补因重写原型失去的constructor属性
        Obj2.prototype.constructor = Obj2

        //添加新的方法
        Obj2.prototype.sayAge = function() {
            console.log(this.age);
        }

        var test1 = new Obj2('Peter', 28)
        test1.colors.push('ddd')
        console.log(test1.colors)
        test1.sayName()
        test1.sayAge()

        var test2 = new Obj2('Greo', 33)
        console.log(test2.colors)
        test2.sayName()
        test2.sayAge()
image.png

优点:组合继承避免了原型链与借用构造函数继承的缺陷,融合入了他们的优点。
缺点:无论在什么情况下,都会调用两次超类型构造函数。一次在创建子类型原型的时候,一次在子类型构造函数内部。

4.寄生式继承

基本思路:创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象。
寄生式继承模式:

        function createAnother(original) {
            var clone = Object.create(original)
            clone.sayHi = function() {
                alert("hi")
            }
            return clone
        }

        var person = {
            name:"Daiv",
            friends:["one","two","three"]
        }

        var anotherPerson = createAnother(person)

        anotherPerson.sayHi()

5.寄生组合式继承

所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
基本思路:
不必为了指定子类型的原型而调用超类型的构造函数,我们需要的无非就是超类型原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。
基本模式如下:

//obj1是子类型结构,obj2是超类型结构
function inheritPrototype(obj1, obj2){
  //第一步:创建超类型原型副本
  var prototype = object(obj2.prototype)
  //第二步:为创建的副本添加constructor属性,弥补因为重写原型而失去的默认的constructor属性
  prototype.constructor = obj1
  //第三步:将新创建的对象(即副本),赋值给子类型的原型
  obj1.prototype = prototype
}

function SuperType(name){
  this.name = name
  this.colors = ["red","blue","green"]
}

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

推荐阅读更多精彩内容