JS學(xué)習(xí)筆記之原型鏈和利用原型實(shí)現(xiàn)繼承詳解
本文實(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("動(dòng)物吃草")
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é)果

我們會(huì)發(fā)現(xiàn) 兩種寫法還是有差別的 ,第二種寫法會(huì)導(dǎo)致constructor構(gòu)造器屬性消失 所以我們得手動(dòng)修改構(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__尋找,直到未找到時(shí)報(bào)錯(cuò)
構(gòu)造函數(shù)和實(shí)例對象和原型對象之間的關(guān)系
構(gòu)造函數(shù)可以實(shí)例化對象
構(gòu)造函數(shù)中有一個(gè)屬性叫prototype,是構(gòu)造函數(shù)的原型對象
構(gòu)造函數(shù)的原型對象(prototype)中有一個(gè)constructor 構(gòu)造器,這個(gè)構(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 的原型對象上添加了一個(gè)eat 方法,也輸出了一個(gè)this,
接著我實(shí)例化了一個(gè)對象,并調(diào)用eat方法,
我們執(zhí)行一下,查看結(jié)果如何

輸出結(jié)果

由此得出
原型對象中方法中的this 就是實(shí)例對象
構(gòu)造函數(shù)中的this就是實(shí)例對象
接下來我們嘗試改變一下原型的指向

這段代碼中,首先我定義了一個(gè)Person自定義構(gòu)造函數(shù),并且在原型上添加了一個(gè)eat方法
定義了一個(gè)Student 函數(shù),在原型上定義了一個(gè)sayHi方法,
然后我將 Student的原型指向 了一個(gè) Person的實(shí)例對象
接著實(shí)例化一個(gè)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__)指向也會(huì)發(fā)生改變
實(shí)例對象和原型對象之間的關(guān)系是通過__proto__ 原型來聯(lián)系起來的,這個(gè)關(guān)系就是原型鏈
如果原型指向改變了,那么就應(yīng)該再原型改變指向之后添加原型方法
那么sayHi方法則會(huì)創(chuàng)建在 new Person(10) 這個(gè)實(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ā),如果兩條路線最終指向一個(gè)引用就是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í)例化多個(gè)Student 都必須共用相同的name 和 age
Student.prototype.constructor=Student
注意: 使用原型繼承時(shí),需要將構(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ù)制,把一個(gè)對象中的屬性和方法直接復(fù)制到另一個(gè)對象中
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];
}
//這個(gè)屬性直接指向父對象的prototype屬性,可以直接調(diào)用父對象的方法,為了實(shí)現(xiàn)繼承的完備性,純屬備用性質(zhì)
c.par = p;
}
5. 直接繼承prototype
優(yōu)點(diǎn) : 效率比較高
缺點(diǎn) : 因?yàn)橄喈?dāng)于是個(gè)傳址過程 所以修改Student的屬性 Person 的也會(huì)被更改
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 不會(huì)影響到 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錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對大家JavaScript程序設(shè)計(jì)有所幫助。
- 詳解JavaScript原型與原型鏈
- 圖解JS原型和原型鏈實(shí)現(xiàn)原理
- 一文秒懂JavaScript構(gòu)造函數(shù)、實(shí)例、原型對象以及原型鏈
- javascript 原型與原型鏈的理解及應(yīng)用實(shí)例分析
- JavaScript對象原型鏈原理解析
- JavaScript中構(gòu)造函數(shù)與原型鏈之間的關(guān)系詳解
- 深入淺析js原型鏈和vue構(gòu)造函數(shù)
- JS原型、原型鏈深入理解
- js原型鏈原理看圖說明
- JS繼承--原型鏈繼承和類式繼承
- javascript prototype 原型鏈
- 一篇文章讓你搞懂JavaScript 原型和原型鏈
相關(guān)文章
詳解JavaScript設(shè)計(jì)模式中的享元模式
享元模式是一種用于性能優(yōu)化的模式。享元模式的核心是運(yùn)用共享技術(shù)來有效支持大量細(xì)粒度的對象.如果系統(tǒng)中創(chuàng)建了大量類似的對象而導(dǎo)致內(nèi)存占用過高,本文通過介紹書中文件上傳的優(yōu)化案例來說明享元模式的使用方式和作用,需要的朋友可以參考下2023-06-06
原生JS實(shí)現(xiàn)網(wǎng)絡(luò)彩票投注效果
分享一個(gè)最近模仿市面彩票系統(tǒng)寫個(gè)小案例,沒有使用任何后臺,從投注到開獎(jiǎng)再到返獎(jiǎng)都是用原生JS實(shí)現(xiàn)的。2016-09-09
JavaScript+HTML5 canvas實(shí)現(xiàn)放大鏡效果完整示例
這篇文章主要介紹了JavaScript+HTML5 canvas實(shí)現(xiàn)放大鏡效果,結(jié)合完整實(shí)例形式分析了javascript+HTML5 canvas針對圖片元素的獲取、響應(yīng)鼠標(biāo)事件變換元素屬性相關(guān)操作技巧,需要的朋友可以參考下2019-05-05
微信小程序嵌入H5頁面(webview)的基本用法和父子傳參數(shù)詳細(xì)說明
微信小程序中嵌入H5頁面通常指的是在小程序中使用Web-view組件來加載外部的網(wǎng)頁,下面這篇文章主要給大家介紹了關(guān)于微信小程序嵌入H5頁面(webview)的基本用法和父子傳參數(shù)的相關(guān)資料,需要的朋友可以參考下2024-08-08
JavaScript+canvas實(shí)現(xiàn)七色板效果實(shí)例
這篇文章主要介紹了JavaScript+canvas實(shí)現(xiàn)七色板效果的方法,結(jié)合實(shí)例形式詳細(xì)分析了JavaScript結(jié)合html5的canvas技術(shù)實(shí)現(xiàn)繪制七色板效果的相關(guān)技巧,需要的朋友可以參考下2016-02-02
Javascript基礎(chǔ)教程之比較null和undefined值
這篇文章主要介紹了Javascript基礎(chǔ)教程之比較null和undefined值的相關(guān)知識,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧2016-05-05
Java?Script網(wǎng)頁設(shè)計(jì)案例詳解
下面我將提供一個(gè)簡單的JavaScript網(wǎng)頁設(shè)計(jì)案例,該案例將實(shí)現(xiàn)一個(gè)動(dòng)態(tài)的待辦事項(xiàng)列表(Todo List),用戶可以在頁面上添加新的待辦事項(xiàng),標(biāo)記它們?yōu)橐淹瓿?以及刪除它們,這篇文章主要介紹了Java?Script網(wǎng)頁設(shè)計(jì)案例,需要的朋友可以參考下2024-08-08
JavaScript樹結(jié)構(gòu)深度優(yōu)先算法
這篇文章主要介紹了JavaScript樹結(jié)構(gòu)深度優(yōu)先算法,樹結(jié)構(gòu)可以說是前端中最常見的數(shù)據(jù)結(jié)構(gòu)之一,比如說DOM樹、級聯(lián)選擇、樹形組件,更多相關(guān)內(nèi)容需要的小伙伴可以參考一下2022-07-07

