成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Javascript面向?qū)ο笈c繼承

pcChao / 1882人閱讀

摘要:眾所周知,是一門(mén)面向?qū)ο蟮恼Z(yǔ)言,如果說(shuō)針對(duì)面向?qū)ο髞?lái)發(fā)問(wèn)的話,我會(huì)想到兩個(gè)問(wèn)題,在中,類與實(shí)例對(duì)象是如何創(chuàng)建的,類與實(shí)例對(duì)象又是如何實(shí)現(xiàn)繼承的。但是在中是指向的,因?yàn)槊恳粋€(gè)構(gòu)造函數(shù)其實(shí)都是這個(gè)對(duì)象構(gòu)造的,中子類的指向父類可以實(shí)現(xiàn)屬性的繼承。

眾所周知,Javascript是一門(mén)面向?qū)ο蟮恼Z(yǔ)言,如果說(shuō)針對(duì)面向?qū)ο髞?lái)發(fā)問(wèn)的話,我會(huì)想到兩個(gè)問(wèn)題,在js中,類與實(shí)例對(duì)象是如何創(chuàng)建的,類與實(shí)例對(duì)象又是如何實(shí)現(xiàn)繼承的。

面向?qū)ο?/b> 如何聲明一個(gè)類

ES5中,還沒(méi)有類的概念,而是通過(guò)函數(shù)來(lái)聲明;到了ES6,有了class關(guān)鍵字,則通過(guò)class來(lái)聲明

      // 類的聲明
      var Animal = function () {
          this.name = "Animal";
      };

      
      // es6中class的聲明
      class Animal2 {
          constructor () {
              this.name = "Animal2";
          }
如何創(chuàng)建對(duì)象

1.字面量對(duì)象
2.顯示的構(gòu)造函數(shù)
3.Object.create

      // 第一種方式:字面量
      var o1 = {name: "o1"};
      var o2 = new Object({name: "o2"});
      // 第二種方式:構(gòu)造函數(shù)
      var M = function (name) { this.name = name; };
      var o3 = new M("o3");
      // 第三種方式:Object.create
      var p = {name: "p"};
      var o4 = Object.create(p);
類與繼承

如何實(shí)現(xiàn)繼承?
繼承的本質(zhì)就是原型鏈

借助構(gòu)造函數(shù)實(shí)現(xiàn)繼承
      /**
       * 借助構(gòu)造函數(shù)實(shí)現(xiàn)繼承
       */
      function Parent1 () {
          this.name = "parent1";
      }
      Parent1.prototype.say = function () {

      };
      function Child1 () {
          Parent1.call(this); // 或Parent1.apply(this,arguments)
          this.type = "child1";
      }
      console.log(new Child1(), new Child1().say());

重點(diǎn)是這句:Parent1.call(this); 在子類的構(gòu)造函數(shù)里執(zhí)行父類的構(gòu)造函數(shù),通過(guò)call/apply改變this指向,從而導(dǎo)致父類構(gòu)造函數(shù)執(zhí)行時(shí)的這些屬性都會(huì)掛載到子類實(shí)例上去。
問(wèn)題: 只能繼承父類構(gòu)造函數(shù)中聲明的實(shí)例屬性,并沒(méi)有繼承父類原型的屬性和方法

借助原型鏈實(shí)現(xiàn)繼承
      /**
       * 借助原型鏈實(shí)現(xiàn)繼承
       */
      function Parent2 () {
          this.name = "parent2";
          this.play = [1, 2, 3];
      }
      function Child2 () {
          this.type = "child2";
      }
      Child2.prototype = new Parent2();

      var s1 = new Child2();
      var s2 = new Child2();
      console.log(s1.play, s2.play);
      s1.play.push(4);

重點(diǎn)就是這句: Child2.prototype = new Parent2(); 就是說(shuō) new 一個(gè)父類的實(shí)例,然后賦給子類的原型 也就是說(shuō) new Child2().__proto__ === Child2.prototype === new Parent2()當(dāng)我們?cè)趎ew Child2()中找不到屬性/方法,順著原型鏈就能找到new Parent2(),這樣就實(shí)現(xiàn)了繼承。
問(wèn)題: 原型鏈中的原型對(duì)象是共用的,子類無(wú)法通過(guò)父類創(chuàng)建私有屬性
比如當(dāng)你new兩個(gè)子類s1、s2的時(shí)候,改s1的屬性,s2的屬性也跟著改變

組合式繼承
      /**
       * 組合方式
       */
      function Parent3 () {
          this.name = "parent3";
          this.play = [1, 2, 3];
      }
      function Child3 () {
          Parent3.call(this); // 父類構(gòu)造函數(shù)執(zhí)行了
          this.type = "child3";
      }
      Child3.prototype = new Parent3(); // 父類構(gòu)造函數(shù)執(zhí)行了
      var s3 = new Child3(); 
      var s4 = new Child3();
      s3.play.push(4);
      console.log(s3.play, s4.play);

組合式就是原型鏈+構(gòu)造函數(shù)繼承,解決了前兩種方法的問(wèn)題,但也有不足:子類實(shí)例化時(shí),父類構(gòu)造函數(shù)執(zhí)行了兩次,所以有了下面的組合繼承的優(yōu)化1

組合繼承的優(yōu)化1
/**
       * 組合繼承的優(yōu)化1
       * @type {String}
       */
      function Parent4 () {
          this.name = "parent4";
          this.play = [1, 2, 3];
      }
      function Child4 () {
          Parent4.call(this);
          this.type = "child4";
      }
      Child4.prototype = Parent4.prototype;
      var s5 = new Child4();
      var s6 = new Child4();
      console.log(s5, s6);

      console.log(s5 instanceof Child4, s5 instanceof Parent4);
      console.log(s5.constructor);

其實(shí)就是把原型鏈繼承的那句 Child4.prototype = new Parent4(); 改為 Child4.prototype = Parent4.prototype; 這樣雖然父類構(gòu)造函數(shù)只執(zhí)行了一次了,但又有了新的問(wèn)題: 無(wú)法判斷s5是Child4的實(shí)例還是Parent4的實(shí)例 因?yàn)镃hild4.prototype.constructor指向了Parent4的實(shí)例;如果直接加一句 Child4.prototype.constructor = Child4 也不行,這樣Parent4.prototype.constructor也指向Child4,就無(wú)法區(qū)分父類實(shí)例了。

若要判斷a是A的實(shí)例  用constructor     
a.__proto__.constructor === A
用instanceof則不準(zhǔn)確, instanceof 判斷 實(shí)例對(duì)象的__proto__ 是不是和 構(gòu)造函數(shù)的prototype 是同一個(gè)引用。若A 繼承 B, B 繼承 C 在該原型鏈上的對(duì)象 用instanceof判斷都返回ture
組合繼承的優(yōu)化2(推薦)
/**
       * 組合繼承的優(yōu)化2
       */
      function Parent5 () {
          this.name = "parent5";
          this.play = [1, 2, 3];
      }
      function Child5 () {
          Parent5.call(this);
          this.type = "child5";
      }
      //注意此處,用到了Object.creat(obj)方法,該方法會(huì)對(duì)傳入的obj對(duì)象進(jìn)行淺拷貝
      //這個(gè)方法作為一個(gè)橋梁,達(dá)到父類和子類的一個(gè)隔離
      Child5.prototype = Object.create(Parent5.prototype);
      //修改構(gòu)造函數(shù)指向
      Child5.prototype.constructor = Child5

構(gòu)造函數(shù)屬性繼承和建立子類和父類原型的鏈接

ES6實(shí)現(xiàn)繼承

引入了class、extends、super關(guān)鍵字,在子類構(gòu)造函數(shù)里調(diào)用super()方法來(lái)調(diào)用父類的構(gòu)造函數(shù)。
在子類的構(gòu)造函數(shù)中,只有調(diào)用super之后,才可以使用this關(guān)鍵字,否則會(huì)報(bào)錯(cuò)。這是因?yàn)樽宇悓?shí)例的構(gòu)建,是基于對(duì)父類實(shí)例加工,只有super方法才能返回父類實(shí)例。

class Child6 extends Parent6 {
      constructor(x, y, color) {
        super(x, y); // 調(diào)用父類的constructor(x, y)
        this.color = color;
      }
      toString() {
        return this.color + " " + super.toString(); // super代表父類原型,調(diào)用父類的toString()
      }
    }
class實(shí)現(xiàn)原理

Class充當(dāng)了ES5中構(gòu)造函數(shù)在繼承實(shí)現(xiàn)過(guò)程中的作用
有prototype屬性,有__proto__屬性,這個(gè)屬性在ES6中的指向有一些主動(dòng)的修改。
同時(shí)存在兩條繼承鏈:一條實(shí)現(xiàn)屬性繼承,一條實(shí)現(xiàn)方法繼承。

class A extends B {}
A.__proto__ === B;  //繼承屬性
A.prototype.__proto__ === B.prototype;  //繼承方法

ES6的子類的__proto__是父類,子類的原型的__proto__是父類的原型。
但是在ES5中 A.__proto__是指向Function.prototype的,因?yàn)槊恳粋€(gè)構(gòu)造函數(shù)其實(shí)都是Function這個(gè)對(duì)象構(gòu)造的,ES6中子類的__proto__指向父類可以實(shí)現(xiàn)屬性的繼承。

只有函數(shù)有prototype屬性,只有對(duì)象有__proto__屬性 ;但函數(shù)也有__proto__屬性,因?yàn)楹瘮?shù)也是一個(gè)對(duì)象,函數(shù)的__proto__等于 Function.prototype。
extends實(shí)現(xiàn)原理
//原型連接
Man.prototype = Object.create(Person.prototype); 
// B繼承A的靜態(tài)屬性
Object.setPrototypeOf(Man, Person);
//綁定this
Person.call(this);

前兩句實(shí)現(xiàn)了原型鏈上的繼承,最后一句實(shí)現(xiàn)構(gòu)造函數(shù)上的繼承。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93997.html

相關(guān)文章

  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對(duì)象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    李昌杰 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對(duì)象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    Lyux 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對(duì)象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    AaronYuan 評(píng)論0 收藏0
  • 面向對(duì)象JavaScript

    摘要:是完全的面向?qū)ο笳Z(yǔ)言,它們通過(guò)類的形式組織函數(shù)和變量,使之不能脫離對(duì)象存在。而在基于原型的面向?qū)ο蠓绞街校瑢?duì)象則是依靠構(gòu)造器利用原型構(gòu)造出來(lái)的。 JavaScript 函數(shù)式腳本語(yǔ)言特性以及其看似隨意的編寫(xiě)風(fēng)格,導(dǎo)致長(zhǎng)期以來(lái)人們對(duì)這一門(mén)語(yǔ)言的誤解,即認(rèn)為 JavaScript 不是一門(mén)面向?qū)ο蟮恼Z(yǔ)言,或者只是部分具備一些面向?qū)ο蟮奶卣?。本文將回歸面向?qū)ο蟊疽?,從?duì)語(yǔ)言感悟的角度闡述為什...

    novo 評(píng)論0 收藏0
  • javascript面向對(duì)象之“多態(tài)”

    摘要:之前,本質(zhì)上不能算是一門(mén)面向?qū)ο蟮木幊陶Z(yǔ)言,因?yàn)樗鼘?duì)于封裝繼承多態(tài)這些面向?qū)ο笳Z(yǔ)言的特點(diǎn)并沒(méi)有在語(yǔ)言層面上提供原生的支持。所以在中出現(xiàn)了等關(guān)鍵字,解決了面向?qū)ο笾谐霈F(xiàn)了問(wèn)題。 ES6之前,javascript本質(zhì)上不能算是一門(mén)面向?qū)ο蟮木幊陶Z(yǔ)言,因?yàn)樗鼘?duì)于封裝、繼承、多態(tài)這些面向?qū)ο笳Z(yǔ)言的特點(diǎn)并沒(méi)有在語(yǔ)言層面上提供原生的支持。但是,它引入了原型(prototype)的概念,可以讓我們以...

    JerryWangSAP 評(píng)論0 收藏0
  • 前端進(jìn)擊的巨人(七):走進(jìn)面向對(duì)象,原型原型鏈,繼承方式

    摘要:除了以上介紹的幾種對(duì)象創(chuàng)建方式,此外還有寄生構(gòu)造函數(shù)模式穩(wěn)妥構(gòu)造函數(shù)模式。 showImg(https://segmentfault.com/img/remote/1460000018196128); 面向?qū)ο?是以 對(duì)象 為中心的編程思想,它的思維方式是構(gòu)造。 面向?qū)ο?編程的三大特點(diǎn):封裝、繼承、多態(tài): 封裝:屬性方法的抽象 繼承:一個(gè)類繼承(復(fù)制)另一個(gè)類的屬性/方法 多態(tài):方...

    wums 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<