前端小白眼中的JS继承---总结

懂得不少道理但依然过不好这一生。

JS继承方法看了不少,但面向对象这块内容实在是太抽象,绕绕的自己就绕进去了,今天看了一篇关于继承方法总结的文章感觉豁然开朗,于是乎自己敲了敲总结一下。新手小白有任何问题还请指正。


方法一:构造函数继承

function Father1() {
    this.father_Property1 = "father_Property111"
    this.father_Property2 = ["aaa","bbb","ccc"]
}   
function Son1() {
    Father1.call(this); // 或apply
    this.type = "son1";
}
    new Son1().father_Property1;
    new Son1().father_Property2;

第六行,子类Son1中执行父类Father1的构造函数通过这种调用,把父类构造函数的this指向为子类实例化对象引用,从而导致父类执行的时候父类里面的属性都会被挂载到子类的实例上去。

console.log(new Son1().father_Property1) //father_Property111
console.log(new Son1().father_Property2)  //["aaa", "bbb", "ccc"]

但是通过这种方式,父类原型上的东西是没法继承的,因此函数复用也就无从谈起。如下:

    Father1.prototype.father_Property3 = "father_Property333";
    Father1.prototype.father_Property4 = function() { 
        console.log("father_Property444"); 
    }
    new Son1().father_Property3;
    new Son1().father_Property4;
    console.log(new Son1().father_Property3) //undefined
    console.log(new Son1().father_Property4) //undefined
缺点:Son1无法继承Father1的原型对象,并没有真正的实现继。生动点来说就是Father1只是Son1的“义父”,Son1只继承到了他的一部分,Father1原型上的对象并没有继承过来

方法二:原型链式继承

function Father2() {
        this.father_Property1 = "father_Property111";
        this.father_Property2 = ["aaa","bbb","ccc"];
    }
    function Son2() {
        this.father_Property1 = "Son2";
    }
    Son2.prototype = new Father2();

首先实现原型链式继承,下面检验一下Son2有没有继承了Father2原型上的属性和方法,我们为Father2的原型添加新属性father_Property3。

Father2.prototype.father_Property3 = "father_Property333"
    new Son2().father_Property3;
    console.log(new Son2().father_Property3)//father_Property333

这种方式解决了构造函数继承方式的缺点,Father2现在是Son2的亲爹了,原型上的属性和方法都继承给了Son2。

但是这里产生了一个问题:

    var s1 =new Son2();
    s1.father_Property2.push("ddd");
    console.log(s1.father_Property2)//["aaa", "bbb", "ccc", "ddd"]
    //再new一个
    var s2 =new Son2();
    console.log(s2.father_Property2) //["aaa", "bbb", "ccc", "ddd"]
缺点:new了两个Son2的实例,s1和s2,我们给s1的 father_Property2属性添加了一个字段,但是最后打印的时候s1和s2的 father_Property2属性都改变了,我们并没有s2.xxx去操作它,s2被s1影响了,造成这种现象的原因就是原型链上中的原型对象它俩是共用的。
这显然不是我们想要的,s1和s2这个两个对象应该是隔离的,这是这种继承方式的缺点。

方法三:组合式继承

构造函数继承和原型链继承两种方式结合起来

function Father3() {
        this.father_Property1 = "father_Property111";
        this.father_Property2 = ["aaa","bbb","ccc"];
    }
    function Son3() {
        Father3.call(this);
        this.type = "son3";
    }
    Son3.prototype = new Father3();

Father3.call(this);
Son3.prototype = new Father3();
这按句话结合了以上两种方法的优点

var s1 =new Son3();
s1.father_Property2.push("ddd");
console.log(s1.father_Property2) //["aaa", "bbb", "ccc", "ddd"]

var s2 =new Son3();
console.log(s2.father_Property2) //["aaa", "bbb", "ccc"]

ok,问题解决
但是!!!!!!没错还有但是
父类的构造函数被执行了两次,第一次是Son3.prototype = new Father3(),第二次是在实例化的时候,这是没有必要的。

优化1:

直接把父类的原型对象赋给子类的原型对象

    function Father3() {
        this.father_Property1 = "father_Property111";
        this.father_Property2 = ["aaa","bbb","ccc"];
    }
    function Son3() {
        Father3.call(this);
        this.type = "son3";
    }
    Son3.prototype = Father3.prototype;

    var s1 =new Son3();
    var s2 =new Son3();

Son3.prototype = Father3.prototype 父类的原型对象赋给子类的原型对象,父类的构造函数被执行了一次,优化get!

但是!!!!!

    console.log(s1 instanceof Son3) //true
    console.log(s1 instanceof Father3) //true

返回结果都是 true 我们无法区分实例对象s1到底是由 Son3 直接实例化的还是 Father3 直接实例化的。

  console.log(s1.constructor.name); // Parent3

可以,自己的东西被爹抢走了
这是因为Son3.prototype = Father3.prototype 不光将Son3继承了Father3,同时还会使Son3的实例化对象指向Father3
s1的构造函数居然是父类,而不是子类Son3,这显然不是我们想要的。

优化2:

最完美方式
    function Father3() {
        this.father_Property1 = "father_Property111";
        this.father_Property2 = ["aaa","bbb","ccc"];
    }
    function Son3() {
        Father3.call(this);
        this.type = "son3";
    }
    Son3.prototype = Object.create(Father3.prototype);
    Son3.prototype.constructor = Son3;

Object.create是一种创建对象的方式
1.方法内部定义一个新的空对象obj
2.将obj._proto _的对象指向传入的参数proto
3.返回一个新的对象

    var s1 =new Son3();
    var s2 =new Son3();
    console.log(s1 instanceof Son3) //true
    console.log(s1 instanceof Father3) //true

    console.log(s1.constructor.name); // Son3
Son3.prototype.constructor = Son3 将错误的指向再给指回来!

完美解决。撒花~


如果您觉得对您有帮助!就请帮我点个喜欢😍😍😍

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

推荐阅读更多精彩内容

  • 重新读《自控力》这本书,响应族长大人精读的号召。精读一本书,比范读10本书要更加有意义。 自控力是很多人都认为缺乏...
    黑土钱阅读 233评论 0 2
  • 让爱恋离开,让你离开,似乎更加适合彼此。 深藏内心的可惜的是,只能放你离开,从此不再联系。 也许还能在网上看到你的...
    Lisaclero阅读 151评论 0 0
  • 当下的世界,知识依然改变着命运。不论是国家,还是个人。这个论断依然不过时。而且,到什么时候也不会过时的。 当下的世...
    公冶鸿基阅读 238评论 0 1