本文實(shí)例講述了javascript 原型與原型鏈的理解。分享給大家供大家參考,具體如下:
成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),南寧企業(yè)網(wǎng)站建設(shè),南寧品牌網(wǎng)站建設(shè),網(wǎng)站定制,南寧網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,南寧網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
javascript中一切皆對(duì)象,但是由于沒有Class類的概念,所以就無(wú)法很好的表達(dá)對(duì)象與對(duì)象之間的關(guān)系了。
比如對(duì)象A與對(duì)象B之間,它們兩個(gè)是相對(duì)獨(dú)立的個(gè)體,互不干擾,對(duì)象A修改自身的屬性不會(huì)影響到對(duì)象B。
雖然這很好,但是有一個(gè)問題,如果對(duì)象A與對(duì)象B都有一個(gè)方法 run() ,并且代碼也一樣,那對(duì)象A與對(duì)象B各自都獨(dú)立擁有一份 run() 方法的完整代碼,這是需要資源去保存的。
一旦我們程序中應(yīng)用的對(duì)象過多,那這種資源消耗會(huì)是巨大的。那有沒有一種方法可以讓對(duì)象A與對(duì)象B擁有一些公共的屬性和方法,讓它們之前有某種聯(lián)系?
我們?cè)O(shè)想一下,會(huì)不會(huì)存在一個(gè) common對(duì)象(公共對(duì)象),common對(duì)象上保存著公共的屬性和方法,而對(duì)象A與對(duì)象B里面有一個(gè)prototype屬性指向這個(gè) common對(duì)象,
當(dāng)然我們調(diào)用對(duì)象A或?qū)ο驜的屬性和方法時(shí),如果在自身對(duì)象中沒有找到,就去prototype這個(gè)屬性指向的對(duì)象上面去找。
而common對(duì)象本身也有一個(gè)prototype屬性指向更上一級(jí)的common對(duì)象,然后一直往上找啊找,直到為null,就停止。
這種不斷的從下往上找的這種路徑,就像鏈條一樣,我們稱它為 原型鏈,而那個(gè)common對(duì)象,我們稱它為 原型對(duì)象。
我們來看一個(gè)構(gòu)造函數(shù)
function Base(name) { this.name = name; } let A = new Base('A'); let B = new Base('B'); //每一個(gè)函數(shù)都有一個(gè)prototype屬性,指向該函數(shù)的原型對(duì)象 console.log(Base.prototype); //當(dāng)然原型對(duì)象也是一個(gè)對(duì)象,它也有一個(gè)constructor,指向構(gòu)造函數(shù) console.log(Base.prototype.constructor === Base); //每一個(gè)實(shí)例對(duì)象的constructor都指向創(chuàng)建它們的構(gòu)造函數(shù) console.log(A.constructor === Base); console.log(B.constructor === Base); //每一個(gè)實(shí)例對(duì)象都有一個(gè)__proto__屬性,該屬性指向構(gòu)造函數(shù)的原型對(duì)象 console.log(A.__proto__ === Base.prototype); console.log(B.__proto__ === Base.prototype);
1、每一個(gè)函數(shù)都有一個(gè)prototype屬性,它指向該函數(shù)的原型對(duì)象。
2、原型對(duì)象也是對(duì)象,它也有自已的constructor,它指向構(gòu)造函數(shù)Base()。換句話說,其實(shí)原型對(duì)象也是構(gòu)造函數(shù)Base()的一個(gè)實(shí)例。只不過比較特殊,用來存放公共屬性和方法的。
3、每一個(gè)通過構(gòu)造函數(shù)Base()創(chuàng)建的實(shí)例對(duì)象,都有一個(gè)constructor,指向創(chuàng)建它們的構(gòu)造函數(shù)。
4、每一個(gè)對(duì)象,都有一個(gè) __proto__ 屬性,指向構(gòu)造函數(shù)Base()的 原型對(duì)象。換句話說,__proto__ 是將 原型 串聯(lián)起來形成鏈條的關(guān)鍵。不然對(duì)象A與對(duì)象B都無(wú)法找到原型對(duì)象上的公共屬性和方法。
function Base(name) { this.name = name; } //我們?cè)谠蛯?duì)象上添加公共屬性 Base.prototype.status = '開始'; //我們?cè)谠蛯?duì)象上添加公共方法 Base.prototype.run = function() { console.log(this.name + ' run ...'); }; let A = new Base('A'); let B = new Base('B'); A.run(); B.run(); console.log(A.status); console.log(B.status); //修改原型上的屬性,則實(shí)例對(duì)象也會(huì)跟著改變 Base.prototype.status = '停止'; console.log(A.status); console.log(B.status);
通過原型與原型鏈,讓對(duì)象與對(duì)象之間有了關(guān)聯(lián)關(guān)系。
那如何通過原型與原型鏈,讓一個(gè)構(gòu)造函數(shù)繼承于另一個(gè)構(gòu)造函數(shù)?
比如,我們要讓構(gòu)造函數(shù)Child 繼承于 構(gòu)造函數(shù)Base,只需要讓 Child 的 prototype 指向 Base的 原型對(duì)象,不就可以了?
function Base(name) { } Base.prototype.name = 'Base'; Base.prototype.run = function () { console.log(this.name + ' run ...'); }; function Child() { } Child.prototype = Base.prototype; //注意這個(gè)時(shí)候,Child.prototype對(duì)象的constructor屬性指向了Base //這就導(dǎo)致通過構(gòu)造函數(shù)Child創(chuàng)建的實(shí)例對(duì)象,對(duì)象的constructor屬性會(huì)指向Base,而不是Child,這會(huì)導(dǎo)致混亂。 //所以我們重新設(shè)置Child.prototype.constructor指向Child Child.prototype.constructor = Child; let c = new Child(); console.log(c.name); c.run();
這樣有一個(gè)問題,Child.prototype 與 Base.prototype 指向同一個(gè)原型對(duì)象,任何對(duì) Child.prototype 的修改都會(huì)反應(yīng)到 Base.prototype 上面。
這時(shí),Base.prototype.constructor 指向了 Child,這顯然是有問題。
我們只能通過一個(gè)中間的空構(gòu)造函數(shù),來完成原型的指向。
function Base(name) { } Base.prototype.name = 'Base'; Base.prototype.run = function () { console.log(this.name + ' run ...'); }; function Child() { } //創(chuàng)建一個(gè)中間的空構(gòu)造函數(shù) function Mid() { } //讓該空構(gòu)造函數(shù)的prototype指向Base的原型對(duì)象 Mid.prototype = Base.prototype; //再讓Child的prototype指向該空構(gòu)造函數(shù)的一個(gè)實(shí)例 Child.prototype = new Mid(); //這樣,當(dāng)修改Child.prototype.constructor時(shí),Base.prototype就不會(huì)受影響了 Child.prototype.constructor = Child; let c = new Child(); console.log(c.name); c.run(); //Base.prototype的constructor仍然指向Base,沒有受到影響 console.log(Base.prototype.constructor);
那怎么通過原型與原型鏈,讓你一對(duì)象繼承于另一個(gè)對(duì)象呢?
比如,我們要讓對(duì)象B繼承于對(duì)象A,無(wú)非就是想要拿到對(duì)象A的屬性和方法,這么一想,那通過把對(duì)象B的 __proto__ 指向 對(duì)象A,不就可以實(shí)現(xiàn)了?
let A = { name: 'A', run() { console.log(this.name + ' run ...'); } }; console.log(A.name); A.run(); let B = {}; //讓對(duì)象B的__proto__指向?qū)ο驛 B.__proto__ = A; //當(dāng)對(duì)象B調(diào)用run()方法時(shí)會(huì)在自身上找,如果沒找到,則通過__proto__向上找 //由于__proto__指向?qū)ο驛,所以最終會(huì)在對(duì)象A中找到run()方法 B.run(); B.__proto__.name = 'B'; console.log(A.name); console.log(B.name);
這樣有一個(gè)問題,當(dāng)修改 B.__proto__.name = 'B'; 時(shí),對(duì)象A也會(huì)受到影響。
我們可以通過ES5提供的 Object.create() 來解決此問題,Object.create()可以通過指定的 原型對(duì)象 創(chuàng)建一個(gè)新對(duì)象。
let A = { name: 'A', run() { console.log(this.name + ' run ...'); } }; console.log(A.name); A.run(); let B = {}; //通過Object.create()創(chuàng)建一個(gè)以對(duì)象A為原型對(duì)象的新對(duì)象 //讓對(duì)象B的__proto__指向該新對(duì)象 //這樣再操作B.__proto__中的屬性就與對(duì)象A無(wú)關(guān)了。 B.__proto__ = Object.create(A); B.run(); B.__proto__.name = 'B'; console.log(A.name); console.log(B.name);
感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運(yùn)行工具:http://tools.jb51.net/code/HtmlJsRun測(cè)試上述代碼運(yùn)行效果。
更多關(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é)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
當(dāng)前標(biāo)題:javascript原型與原型鏈的理解及實(shí)例分析
路徑分享:http://bm7419.com/article4/goesoe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、搜索引擎優(yōu)化、響應(yīng)式網(wǎng)站、服務(wù)器托管、App設(shè)計(jì)、小程序開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)