日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

JS原形與原型鏈深入詳解

瀏覽:202日期:2024-05-09 11:06:14

本文實(shí)例講述了JS原形與原型鏈。分享給大家供大家參考,具體如下:

前言

在JS中,我們經(jīng)常會(huì)遇到原型。字面上的意思會(huì)讓我們認(rèn)為,是某個(gè)對(duì)象的原型,可用來(lái)繼承。但是其實(shí)這樣的理解是片面的,下面通過(guò)本文來(lái)了解原型與原型鏈的細(xì)節(jié),再順便談?wù)劺^承的幾種方式。

原型

在講到原型之前,我們先來(lái)回顧一下JS中的對(duì)象。在JS中,萬(wàn)物皆對(duì)象,就像字符串、數(shù)值、布爾、數(shù)組等。ECMA-262把對(duì)象定義為:無(wú)序?qū)傩缘募希鋵傩钥砂局怠?duì)象或函數(shù)。對(duì)象是擁有屬性和方法的數(shù)據(jù),為了描述這些事物,便有了原型的概念。

無(wú)論何時(shí),只要?jiǎng)?chuàng)建了一個(gè)新函數(shù),就會(huì)根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個(gè)prototype屬性,這個(gè)屬性指向該函數(shù)的原型對(duì)象。所有原型對(duì)象都會(huì)獲得一個(gè)constructor屬性,這個(gè)屬性包含一個(gè)指向prototype屬性所在函數(shù)的指針。

這段話摘自《JS高級(jí)程序設(shè)計(jì)》,很好理解,以創(chuàng)建實(shí)例的代碼為例。

function Person(name, age) { this.name = name; this.age = age; this.sayName = function() { alert(this.name); };}const person1 = new Person('gali', 18);const person2 = new Person('pig', 20);

JS原形與原型鏈深入詳解

上面例子中的person1跟person2都是構(gòu)造函數(shù)Person()的實(shí)例,Person.prototype指向了Person函數(shù)的原型對(duì)象,而Person.prototype.constructor又指向Person。Person的每一個(gè)實(shí)例,都含有一個(gè)內(nèi)部屬性__proto__,指向Person.prototype,就像上圖所示,因此就有下面的關(guān)系。

console.log(Person.prototype.constructor === Person); // trueconsole.log(person1.__proto__ === Person.prototype); // trueconsole.log(person2.__proto__ === Person.prototype); // true繼承

JS是基于原型的語(yǔ)言,跟基于類的面向?qū)ο笳Z(yǔ)言有所不同,JS中并沒(méi)有類這個(gè)概念,有的是原型對(duì)象這個(gè)概念,原型對(duì)象作為一個(gè)模板,新對(duì)象可從原型對(duì)象中獲得屬性。那么JS具體是怎樣繼承的呢?

在講到繼承這個(gè)話題之前,我們先來(lái)理解原型鏈這個(gè)概念。

原型鏈

構(gòu)造函數(shù),原型和實(shí)例的關(guān)系已經(jīng)很清楚了。每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象,原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針,而實(shí)例對(duì)象都包含一個(gè)指向與原型對(duì)象的指針。這樣的關(guān)系非常好理解,但是如果我們想讓原型對(duì)象等于另一個(gè)類型的實(shí)例對(duì)象呢?那么就會(huì)衍生出相同的關(guān)系,此時(shí)的原型對(duì)象就會(huì)含有一個(gè)指向另一個(gè)原型對(duì)象的指針,而另一個(gè)原型對(duì)象會(huì)含有一個(gè)指向另一個(gè)構(gòu)造函數(shù)的指針。如果另一個(gè)原型對(duì)象又是另一個(gè)類型的實(shí)例對(duì)象呢?這樣就構(gòu)成了原型鏈。文字可能有點(diǎn)難理解,下面用代碼舉例。

function SuperType() { this.name = '張三';}SuperType.prototype.getSuperName = function() { return this.name;};function SubType() { this.subname = '李四';}SubType.prototype = new SuperType();SubType.prototype.getSubName = function() { return this.subname;};const instance = new SubType();console.log(instance.getSuperName()); // 張三

上述例子中,SubType的原型對(duì)象作為SuperType構(gòu)造函數(shù)的實(shí)例對(duì)象,此時(shí),SubType的原型對(duì)象就會(huì)有一個(gè)__proto__屬性指向SuperType的原型對(duì)象,instance作為SubType的實(shí)例對(duì)象,必然能共享SubType的原型對(duì)象的屬性,又因?yàn)镾ubType的原型對(duì)象又指向SuperType原型對(duì)象的屬性,因此可得,instance繼承了SuperType原型的所有屬性。

我們都知道,所有函數(shù)的默認(rèn)原型都是Object的實(shí)例,所以也能得出,SuperType的默認(rèn)原型必然有一個(gè)__proto__指向Object.prototype。

圖中由__proto__屬性組成的鏈子,就是原型鏈,原型鏈的終點(diǎn)就是null

JS原形與原型鏈深入詳解

上圖可很清晰的看出原型鏈的結(jié)構(gòu),這不禁讓我想到JS的一個(gè)運(yùn)算符instanceof,instanceof可用來(lái)判斷一個(gè)實(shí)例對(duì)象是否屬于一個(gè)構(gòu)造函數(shù)。

A instanceof B; // true

實(shí)現(xiàn)原理其實(shí)就是在A的原型鏈上尋找是否有原型等于B.prototype,如果一直找到A原型鏈的頂端null,仍然找不到原型等于B.prototype,那么就可返回false。下面手寫一個(gè)instanceof,這個(gè)也是很多大廠常用的手寫面試題。

function Instance(left, right) { left = left.__proto__; right = right.prototype; while (true) { if (left === null) return false; if (left === right) return true; // 繼續(xù)在left的原型鏈向上找 left = left.__propo__; }}原型鏈繼承

上面例子中,instance繼承了SuperType原型的屬性,其繼承的原理其實(shí)就是通過(guò)原型鏈實(shí)現(xiàn)的。原型鏈很強(qiáng)大,可用來(lái)實(shí)現(xiàn)繼承。可是單純的原型鏈繼承也是有問(wèn)題存在的。

實(shí)例屬性變成原型屬性,影響其他實(shí)例 創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)傳遞參數(shù)

function SuperType() { this.colorArr = ['red', 'blue', 'green'];}function SubType() {}SubType.prototype = new SuperType();const instance1 = new SubType();instance1.colorArr.push('black');console.log(instance1.colorArr); // ['red', 'blue', 'green', 'black']const instance2 = new SubType();console.log(instance2.colorArr); // ['red', 'blue', 'green', 'black']

當(dāng)SubType的原型作為SuperType的實(shí)例時(shí),此時(shí)SubType的實(shí)例對(duì)象通過(guò)原型鏈繼承到colorArr屬性,當(dāng)修改了其中一個(gè)實(shí)例對(duì)象從原型鏈中繼承到的原型屬性時(shí),便會(huì)影響到其他實(shí)例。對(duì)instance1.colorArr的修改,在instance2.colorArr便能體現(xiàn)出來(lái)。

組合繼承

組合繼承指的是組合原型鏈和構(gòu)造函數(shù)的技術(shù),通過(guò)原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,而通過(guò)借用構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。

function SuperType(name) { this.name = name; this.colors = ['red', 'blue', 'green'];}SuperType.prototype.sayName = function() { console.log(this.name);};function SubType(name, age) { // 繼承屬性,借用構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承 SuperType.call(this, name); this.age = age;}// 繼承原型屬性及方法SubType.prototype = new SuperType();SubType.prototype.constructor = SubType;SubType.prototype.sayAge = function() { console.log(this.age);};const instance1 = new SubType('gali', 18);instance1.colors.push('black');console.log(instance1.colors); // ['red', 'blue', 'green', 'black']instance1.sayName(); // galiinstance1.sayAge(); // 18const instance2 = new SubType('pig', 20);console.log(instance2.colors); // ['red', 'blue', 'green']instance2.sayName(); // piginstance2.sayAge(); // 20

上述例子中,借用構(gòu)造函數(shù)繼承實(shí)例屬性,通過(guò)原型繼承原型屬性與方法。這樣就可讓不同的實(shí)例分別擁有自己的屬性,又可共享相同的方法。而不會(huì)像原型繼承那樣,對(duì)實(shí)例屬性的修改影響到了其他實(shí)例。組合繼承是JS最常用的繼承方式。

寄生組合式繼承

雖然說(shuō)組合繼承是最常用的繼承方式,但是有沒(méi)有發(fā)現(xiàn),就上面的例子中,組合繼承中調(diào)用了2次SuperType函數(shù)。回憶一下,在第一次調(diào)用SubType時(shí)。

SubType.prototype = new SuperType();

這里調(diào)用完之后,SubType.prototype會(huì)從SuperType繼承到2個(gè)屬性:name和colors。這2個(gè)屬性存在SubType的原型中。而在第二次調(diào)用時(shí),就是在創(chuàng)造實(shí)例對(duì)象時(shí),調(diào)用了SubType構(gòu)造函數(shù),也就會(huì)再調(diào)用一次SuperType構(gòu)造函數(shù)。

SuperType.call(this, name);

第二次調(diào)用之后,便會(huì)在新的實(shí)例對(duì)象上創(chuàng)建了實(shí)例屬性:name和colors。也就是說(shuō),這個(gè)時(shí)候,實(shí)例對(duì)象跟原型對(duì)象擁有2個(gè)同名屬性。這樣實(shí)在是浪費(fèi),效率又低。

為了解決這個(gè)問(wèn)題,引入了寄生組合繼承方式。重點(diǎn)就在于,不需要為了定義SubType的原型而去調(diào)用SuperType構(gòu)造函數(shù),此時(shí)只需要SuperType原型的一個(gè)副本,并將其賦值給SubType的原型即可。

function InheritPrototype(subType, superType) { // 創(chuàng)建超類型原型的一個(gè)副本 const prototype = Object(superType.prototype); // 添加constructor屬性,因?yàn)橹貙懺蜁?huì)失去constructor屬性 prototype.constructor = subType; subType.prototype = prototype;}

將組合繼承中的:

SubType.prototype = new SuperType();SubType.prototype.constructor = SubType;

替換成:

InheritPrototype(SubType, SuperType);

寄生組合繼承的優(yōu)點(diǎn)在于,只需要調(diào)用一次SuperType構(gòu)造函數(shù)。避免了在SubType的原型上創(chuàng)建多余的不必要的屬性。

總結(jié)

溫故而知新,再次看回《JS高級(jí)程序設(shè)計(jì)》這本書的原型與原型鏈部分,發(fā)現(xiàn)很多以前忽略掉的知識(shí)點(diǎn)。而這次回看這個(gè)知識(shí)點(diǎn),并輸出了一篇文章,對(duì)我來(lái)說(shuō)受益匪淺。寫文章往往不是為了寫出怎樣的文章,其實(shí)中間學(xué)習(xí)的過(guò)程才是最享受的。

感興趣的朋友可以使用在線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ì)有所幫助。

標(biāo)簽: JavaScript
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美精品日日操| 狠狠色综合网| 久久aⅴ国产紧身牛仔裤| 宅男在线一区| 亚洲a在线视频| 成人羞羞视频播放网站| 欧美国产极品| 婷婷综合福利| 亚洲精品进入| 国产精品麻豆成人av电影艾秋| 欧美综合国产| 亚洲黄页一区| 国产视频一区免费看| 日韩视频一区| 蜜臀a∨国产成人精品| 亚洲区国产区| 亚洲2区在线| 国产日产高清欧美一区二区三区| 国产欧美日韩精品一区二区免费| 久久av免费| 欧美好骚综合网| 成人午夜网址| 肉色欧美久久久久久久免费看 | 亚洲无线一线二线三线区别av| 99久久夜色精品国产亚洲狼 | 免费在线小视频| 亚洲第一区色| 免费观看久久久4p| 青青草国产成人99久久| 欧美国产免费| 日韩欧美中文| 亚洲第一区色| 日韩一区二区三区精品| 麻豆精品在线视频| 日韩在线看片| 丝袜美腿亚洲一区| 欧美国产另类| 在线成人直播| 欧美在线黄色| 日韩av免费大片| 亚洲精品极品少妇16p| 久久精品99国产精品日本| 精品在线91| 精品三级在线观看视频| 欧美黄页在线免费观看| 日本综合字幕| 欧美特黄一级| 国产欧美日韩一区二区三区四区 | 欧美日韩亚洲三区| 麻豆理论在线观看| 久久亚洲国产精品一区二区| 国产精品任我爽爆在线播放| 日韩一区三区| 日本在线视频一区二区| 欧美xxxx中国| 亚洲视频国产| 中文字幕成在线观看| 蜜臀va亚洲va欧美va天堂| 国产精品大片| 久久麻豆精品| 国产伦精品一区二区三区视频 | 国产一区调教| 免费成人av在线播放| 精品欧美日韩精品| 国产视频一区三区| 国产精品伦理久久久久久| 免费在线观看成人| 四季av一区二区凹凸精品| 丝瓜av网站精品一区二区| 精品伊人久久| 亚洲制服一区| 中文字幕系列一区| 国产亚洲电影| 91成人精品视频| 国产精品午夜一区二区三区| 国产伊人精品| 久久九九精品| 婷婷综合亚洲| 成人影视亚洲图片在线| 日韩啪啪电影网| 久久精品国产99久久| 中文字幕av一区二区三区四区| 精品国产精品国产偷麻豆| 99精品在线免费在线观看| 国产欧美日韩一级| 蜜桃av一区二区| 不卡视频在线| 黑森林国产精品av| 国产亚洲一区| 免费人成精品欧美精品| 日韩电影免费网站| 日韩国产高清在线| 在线日韩中文| 国产日韩欧美中文在线| 蜜臀a∨国产成人精品| 香蕉精品视频在线观看| 激情黄产视频在线免费观看| 国产精东传媒成人av电影| 中文字幕一区二区av| 欧美在线亚洲| 亚洲成人va| 精品国产a一区二区三区v免费| 亚洲ww精品| 日韩一级不卡| 亚洲福利久久| 999国产精品999久久久久久| 激情久久99| 国产一区二区亚洲| 美女视频黄久久| 国产欧美日韩精品高清二区综合区 | 国产 日韩 欧美一区| 国产精品115| 久久精品99国产精品| 亚洲人成网站在线在线观看| 久久要要av| 久久高清精品| 蜜桃视频在线网站| 美女视频黄久久| 国产精品一级| 欧美精品三级在线| 日本aⅴ亚洲精品中文乱码| 中文不卡在线| 麻豆亚洲精品| 国产伊人精品| 国产精品av一区二区| 99精品综合| 成人午夜国产| 国产在线欧美| 激情五月综合| 欧美1级日本1级| 亚洲第一区色| 精品在线99| 影音先锋久久| 中文久久精品| 蜜臀久久99精品久久久画质超高清| 亚洲激情欧美| 午夜亚洲福利在线老司机| 伊人成人在线视频| 久久伦理在线| 一区在线观看| 性欧美长视频| 一区二区电影| 亚洲一二三区视频| 日韩欧美精品一区二区综合视频| 亚洲欧美日韩专区| 亚洲一区二区网站| 男人操女人的视频在线观看欧美| 亚洲综合不卡| 亚洲一二三区视频| 亚洲欧洲专区| 日本中文字幕视频一区| 91亚洲精品视频在线观看| 国产探花在线精品| 91亚洲无吗| 国产精品久久久久久久久久妞妞| 国产伦精品一区二区三区视频| 国产精品极品国产中出| 久久久国产精品入口麻豆| 岛国av免费在线观看| 欧美日韩国产传媒| 日本麻豆一区二区三区视频| 欧美交a欧美精品喷水| 天堂中文在线播放| 宅男在线一区| 日本一区中文字幕| 精品美女在线视频| 午夜久久tv| 日韩高清二区| 精品伊人久久久| 久久理论电影| 美国三级日本三级久久99| 国产日本亚洲| 日本欧美不卡| 91精品国产成人观看| 国产偷自视频区视频一区二区| 亚洲人成精品久久久| 国产伦精品一区二区三区在线播放| 国产一区日韩| 欧美手机在线| 欧美亚洲三级| 在线一区av| 亚洲一区二区日韩| 久久97视频| 免费黄色成人| 国产精品网在线观看| 色老板在线视频一区二区| 羞羞答答国产精品www一本| 91免费精品国偷自产在线在线| 精品日韩在线| 美女精品在线观看| 老司机精品在线| 自拍日韩欧美| 国产精品mm| 欧美日韩视频| 美女久久久精品| 久久国产66| 日韩精品2区| 日本精品在线播放| 蜜臀久久精品| 日韩综合一区二区|