国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

JS學(xué)習(xí)筆記之原型鏈和利用原型實(shí)現(xiàn)繼承詳解

2019-11-19 11:26:27
字體:
供稿:網(wǎng)友

本文實(shí)例講述了JS學(xué)習(xí)筆記之原型鏈和利用原型實(shí)現(xiàn)繼承。分享給大家供大家參考,具體如下:

原型鏈

原型鏈?zhǔn)且环N關(guān)系,實(shí)例對象和原型對象之間的關(guān)系,關(guān)系是通過原型(__proto__)來聯(lián)系的

實(shí)例對象中有__proto__,是對象,叫原型,不是標(biāo)準(zhǔn)的屬性,瀏覽器使用,并且有的游覽器不支持
構(gòu)造函數(shù)中有prototype屬性,也是對象,叫原型

注意 原型中的方法是可以互相訪問的

實(shí)例代碼

 function Animal(name,age){    this.name=name;    thia.age=age;   }   //在原型中添加方法   Animal.prototype.eat=function(){    console.log("動物吃草")    this.play()   }   Animal.prototype.play=function(){    console.log("玩啥呢")   }

原型的簡單語法  

利用原型共享數(shù)據(jù)

第一種 寫法

 function Student(name,age,sex){      this.name=name;      this.age=age;      this.sex=sex;   }     Student.prototype.height="188"   Student.prototype.weight="55kg"   Student.prototype.study=function(){      console.log("好好學(xué)習(xí)i")    }  var stu=new Student("小紅",20,"男")  console.dir(stu)

結(jié)果

第二種 寫法

 function Student(name,age,sex){      this.name=name;      this.age=age;      this.sex=sex;   }  Student.prototype={    height:"188",    weight:"55kg",    study:function(){      console.log("好好學(xué)習(xí)i")    }   }  var stu=new Student("小紅",20,"男")  console.dir(stu)


結(jié)果


我們會發(fā)現(xiàn) 兩種寫法還是有差別的  ,第二種寫法會導(dǎo)致constructor構(gòu)造器屬性消失 所以我們得手動修改構(gòu)造器指向

最終代碼

function Student(name,age,sex){      this.name=name;      this.age=age;      this.sex=sex;   }  Student.prototype={    constructor:Student,    height:"188",    weight:"55kg",    study:function(){      console.log("好好學(xué)習(xí)i")    }   }  var stu=new Student("小紅",20,"男")  console.dir(stu)


好了,這回有了


實(shí)例對象使用屬性或方法的規(guī)則

實(shí)例對象使用的屬性或方法,現(xiàn)在實(shí)例中查找,如果有則使用自身的屬性或方法,
如果沒有,則通過__proto__指向的原型對象 查找方法,找到則使用,
如果找不到則繼續(xù)向__proto__尋找,直到未找到時報(bào)錯

構(gòu)造函數(shù)和實(shí)例對象和原型對象之間的關(guān)系

     構(gòu)造函數(shù)可以實(shí)例化對象
     構(gòu)造函數(shù)中有一個屬性叫prototype,是構(gòu)造函數(shù)的原型對象
     構(gòu)造函數(shù)的原型對象(prototype)中有一個constructor 構(gòu)造器,這個構(gòu)造器指向的就是自己所在的原型對象所在的構(gòu)造函數(shù)
     實(shí)例對象的原型對象(__proto__) 指向的是該構(gòu)造函數(shù)的原型對象(prototype)
     構(gòu)造函數(shù)的原型對象(prototype)中的方法是可以被實(shí)例對象直接訪問

改變原型是否可以改變?

首先我們得知道構(gòu)造函數(shù)和實(shí)例對象中的this 指向的是什么

這里我創(chuàng)建了自定義構(gòu)造函數(shù) Person ,并在內(nèi)部輸出了this 

并且在Person 的原型對象上添加了一個eat 方法,也輸出了一個this,

接著我實(shí)例化了一個對象,并調(diào)用eat方法,

我們執(zhí)行一下,查看結(jié)果如何


輸出結(jié)果


由此得出

原型對象中方法中的this 就是實(shí)例對象

構(gòu)造函數(shù)中的this就是實(shí)例對象

接下來我們嘗試改變一下原型的指向

這段代碼中,首先我定義了一個Person自定義構(gòu)造函數(shù),并且在原型上添加了一個eat方法

定義了一個Student 函數(shù),在原型上定義了一個sayHi方法,

然后我將 Student的原型指向 了一個 Person的實(shí)例對象

接著實(shí)例化一個Student,接著分別在stu 實(shí)例上 嘗試著調(diào)用 eat方法 和 sayHi 方法,

運(yùn)行結(jié)果


到此我們可以確定,stu實(shí)例對象原型指向被下面這條代碼改變了

Student.prototype=new Person(10);

總結(jié)

原型指向可以被改變的

實(shí)例對象的原型__proto__指向的是該對象所在的構(gòu)造函數(shù)的原型對象

構(gòu)造函數(shù)的原型對象(prototype)指向如果改變了,實(shí)例對象的原型(__proto__)指向也會發(fā)生改變

實(shí)例對象和原型對象之間的關(guān)系是通過__proto__ 原型來聯(lián)系起來的,這個關(guān)系就是原型鏈

如果原型指向改變了,那么就應(yīng)該再原型改變指向之后添加原型方法

那么sayHi方法則會創(chuàng)建在 new Person(10) 這個實(shí)例對象上

原型最終指向了哪里

實(shí)例對象中的__proto__指向的是構(gòu)造函數(shù)的prototype

以此代碼為例


測試一下



所以

per實(shí)例對象的__proto__ ---指向--->  Person.prototype的__proto__  ---指向--->  Object.prototype的__proto__ 是Null

查看了一下html的dom對象,這有很有意思的原型鏈


這里祭出祖?zhèn)鱆PG

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

小知識---->instanceof的判斷方法:

從左邊操作數(shù)的__proto__路線出發(fā),從右邊操作數(shù)的prototype出發(fā),如果兩條路線最終指向一個引用就是true了

1.利用 call 借用構(gòu)造函數(shù)繼承

優(yōu)點(diǎn):實(shí)現(xiàn)了繼承屬性,但值都不相同

缺點(diǎn): 無法繼承父級類別中原型上的方法

function Person(name,age,sex,weight){  this.name=name;  this.age=age;  this.sex=sex;  this.weight=weight;}Person.prototype.sayHi=function(){  console.log("您好")}function Student(name,age,sex,weight,score){  //將當(dāng)前實(shí)例對象傳入Person 借過來使用一次來達(dá)到繼承效果  Person.call(this,name,age,sex,weight);  this.score=score;}var stu1=new Student("小明",10,"男","10kg","100")

2.  prototype 實(shí)現(xiàn)繼承

利用prototype,將Student 的prototype 指向 Person 來達(dá)到繼承效果,

優(yōu)點(diǎn):繼承了父級原型上的方法

缺點(diǎn):   實(shí)例化多個Student 都必須共用相同的name 和 age 

Student.prototype.constructor=Student

注意:   使用原型繼承時,需要將構(gòu)造器的指向更改回正確的指向

function Person(name,age){    this.name=name;    this.age=age;   }   Person.prototype.eat=function(){    console.log("Person 吃飯")   }   function Student(num,score){    this.num=num    this.score=score   }   //繼承  Student.prototype=new Person("小紅",10)  Student.prototype.constructor=Student  var stu =new Student(2016002288,80)  stu.eat()//Person 吃飯

3.組合繼承

組合繼承其實(shí)就是結(jié)合了上述的兩種方法來實(shí)現(xiàn)繼承,擁有兩種方法的優(yōu)點(diǎn)

function Person(name,age,sex){    this.name=name;    this.age=age;    this.sex=sex;   }   Person.prototype.sayHi=function(){    console.log("你好")   }   function Student(name,age,sex,score){    //借用構(gòu)造函數(shù)    Person.call(this,name,age,sex)    this.score=score   }   // 改變了原型指向   Student.prototype=new Person();//不傳值   Student.prototype.eat=function(){    console.log("吃東西");   }   var stu=new Student("小黑",20,"男","100分")   console.log(stu.name,stu.age,stu.sex,stu.score);   stu.sayHi()//你好   stu.eat()//吃東西

4.拷貝繼承

類似于復(fù)制,把一個對象中的屬性和方法直接復(fù)制到另一個對象中

function Person(){  }  Person.prototype.name="小紅"  Person.prototype.age=18  function Student(){  }    var p=Person.prototype;  var s=Student.prototype;  for(key in p){    s[key]=p[key]  }  console.dir(Student)

console


每次都要for in 好累 ,  可以進(jìn)行優(yōu)化封裝一下

function extend(Child,Parent) {    var p = Parent.prototype;    var c = Child.prototype;    for (var i in p) {      c[i] = p[i];      }        //這個屬性直接指向父對象的prototype屬性,可以直接調(diào)用父對象的方法,為了實(shí)現(xiàn)繼承的完備性,純屬備用性質(zhì)    c.par = p;  }

5. 直接繼承prototype

優(yōu)點(diǎn) : 效率比較高

缺點(diǎn) : 因?yàn)橄喈?dāng)于是個傳址過程 所以修改Student的屬性 Person 的也會被更改 

  function Person(){};  Person.prototype.name="小紅";  Person.prototype.age=18;  function Student(){};  Student.prototype=Person.prototype;  console.dir(Student);  console.dir(Person);  Student.prototype.age=25;

console


6.利用空對象作中介實(shí)現(xiàn)繼承

用這種方式修改 Student 的prototype 不會影響到 Person的prototype

function Person(){};  Person.prototype.name="小紅";  Person.prototype.age=11;  function Student(){};  var F=function(){};  F.prototype=Person.prototype;  Student.prototype=new F();  Student.prototype.constructor=Student;  Student.prototype.age=25;  console.dir(Person)  console.dir(Student)

console


封裝一下

function extend(Child,Parent) {    var F = function(){};    F.prototype = Parent.prototype;    Child.prototype = new F();    Child.prototype.constructor = Child;    Child.par = Parent.prototype;  }

更多關(guān)于JavaScript相關(guān)內(nèi)容還可查看本站專題:《javascript面向?qū)ο笕腴T教程》、《JavaScript錯誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)

希望本文所述對大家JavaScript程序設(shè)計(jì)有所幫助。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 武宁县| 泰和县| 刚察县| 海盐县| 太康县| 萨迦县| 衡水市| 桂东县| 固原市| 许昌县| 青海省| 通化市| 宁海县| 白沙| 临西县| 横峰县| 鹿邑县| 旌德县| 元阳县| 黎川县| 海南省| 浦东新区| 江源县| 汉寿县| 额济纳旗| 大渡口区| 镇江市| 虞城县| 尉氏县| 万源市| 焉耆| 尼木县| 徐汇区| 曲周县| 兴海县| 邢台县| 邢台县| 隆林| 思南县| 巍山| 忻州市|