摘要:此貼用于記錄原型鏈相關(guān)的一些東西。在里,函數(shù)都有,對(duì)象都有,一個(gè)函數(shù)的和一個(gè)對(duì)象的就是原型,原型其實(shí)也是一個(gè)對(duì)象。如果原型鏈很長,當(dāng)訪問某個(gè)屬性的時(shí)候,會(huì)話更多的時(shí)間,需要注意原型鏈不要太長。在引入的之前,函數(shù)的繼承就是通過原型來實(shí)現(xiàn)的。
此貼用于記錄原型鏈相關(guān)的一些東西。
在JavaScript里,函數(shù)都有prototype,對(duì)象都有__proto__,一個(gè)函數(shù)的prototype和一個(gè)對(duì)象的__proto__就是原型,原型其實(shí)也是一個(gè)對(duì)象。
一個(gè)函數(shù)的prototype和這個(gè)函數(shù)的示例對(duì)象的__proto__是同一個(gè)引用,即:
function A(){ } let a = new A(); console.log(a.__proto__ === A.prototype); //返回的是true
當(dāng)調(diào)用某一個(gè)對(duì)象的方法的時(shí)候,如果找不到這個(gè)對(duì)象的方法,則會(huì)去找這個(gè)對(duì)象的原型里的方法,如果再找不到,則繼續(xù)找原型的原型的方法,一直往上找,這個(gè)就是原型鏈,如果都找不到,則會(huì)報(bào)錯(cuò)。
如果原型鏈很長,當(dāng)訪問某個(gè)屬性的時(shí)候,會(huì)話更多的時(shí)間,需要注意原型鏈不要太長。
在引入es6的extends之前,函數(shù)的繼承就是通過原型來實(shí)現(xiàn)的。下面記錄一下我理解的繼承,下面的繼承參考的是[JS繼承的實(shí)現(xiàn)方式
][1],他那里有完整的繼承方法。
function A(name) { this.name = name; this.f1 = function () { console.log(this.name + "正在做f1"); } } A.prototype.f2 = function () { console.log(this.name + "正在做f2"); } function B(name) { this.name = name; } B.prototype = new A(""); let b = new B("test"); b.f1(); b.f2(); console.log(b.__proto__ === B.prototype); //true console.log(b instanceof A);//true console.log(b instanceof B);//true
上述例子中,b居然是A的實(shí)例對(duì)象,也是B的實(shí)例對(duì)象,這樣其實(shí)是有問題的,需要在B.prototype = new A("");后面加上:
B.prototype.constructor = B;
優(yōu)點(diǎn):
1.簡單,實(shí)現(xiàn)容易
2.能訪問父類所有的方法和屬性
缺點(diǎn):
1.要給B的prototype新增方法必須要在 new A("");之后
2.無法實(shí)現(xiàn)多繼承
3.沒法向父類的構(gòu)造函數(shù)傳遞參數(shù)
4.實(shí)例是當(dāng)前類的實(shí)例,也是父類的實(shí)例
function A(name){ this.name = name; this.f1 = function(){ console.log(this.name + "正在做f1"); } } A.prototype.f2 = function(){ console.log(this.name + "正在做f2"); } function B(name) { A.call(this, name); } let b = new B("test"); b.f1(); // b.f2();// 會(huì)報(bào)錯(cuò) console.log(b instanceof A);//false console.log(b instanceof B);//true
優(yōu)點(diǎn):
1.可以使用父類的屬性和方法
2.可以實(shí)現(xiàn)多重繼承,即可以call多個(gè)函數(shù)
3.實(shí)例對(duì)象是當(dāng)前類的實(shí)例,不是父類的實(shí)例
缺點(diǎn):
1.無法獲取A的prototype的屬性和方法
2.只是子類的實(shí)例,不是父類的實(shí)例
3.無法實(shí)現(xiàn)函數(shù)復(fù)用,每個(gè)子類都有父類實(shí)例函數(shù)的副本,影響性能(此處應(yīng)該是調(diào)用call的時(shí)候會(huì)生成父類的實(shí)例副本,具體的還得再研究研究)
function A(name){ this.name = name; this.f1 = function(){ console.log(this.name + "正在做f1"); } } A.prototype.f2 = function(){ console.log(this.name + "正在做f2"); } function B(name) { A.call(this, name); } B.prototype = new A(""); //要修正prototype的constructor,為什么要修正還有待研究 B.prototype.constructor = B; let b = new B("test"); b.f1(); b.f2(); console.log(b instanceof A);//true console.log(b instanceof B);//true
優(yōu)點(diǎn):
1.包含了原型鏈繼承和構(gòu)造繼承的優(yōu)點(diǎn)
2.解決了原型鏈繼承的無法實(shí)現(xiàn)多繼承和沒法向父類的構(gòu)造函數(shù)傳遞參數(shù)的缺點(diǎn)
3.解決了構(gòu)造繼承無法獲取A的prototype的屬性和方法還有只是子類的實(shí)例,不是父類的實(shí)例的問題
缺點(diǎn):
1.調(diào)用了兩次父類構(gòu)造函數(shù),生成了兩份實(shí)例(子類實(shí)例將子類原型上的那份屏蔽了)
function A(name){ this.name = name; this.f1 = function(){ console.log(this.name + "正在做f1"); } } A.prototype.f2 = function(){ console.log(this.name + "正在做f2"); } function B(name) { A.call(this, name); } (function(){ // 創(chuàng)建一個(gè)沒有實(shí)例方法的類 var Super = function(){}; Super.prototype = A.prototype; //將實(shí)例作為子類的原型,這樣就可以只獲取A的prototype的屬性了 B.prototype = new Super(); // B.prototype.constructor = B; })(); let b = new B("test"); b.f1(); b.f2(); console.log(b instanceof A);//true console.log(b instanceof B);//true
優(yōu)點(diǎn):
1.在組合繼承的基礎(chǔ)上,只生成了一份父類的實(shí)例,prototype也只繼承了父類的prototype,沒有繼承私有的屬性
缺點(diǎn):
1.實(shí)現(xiàn)復(fù)雜
順便加一個(gè)知識(shí)點(diǎn),當(dāng)使用new關(guān)鍵字來創(chuàng)建對(duì)象的時(shí)候,也用到了原型相關(guān)的知識(shí),所以也記在了這里;
假設(shè)有一個(gè)function A(name){ this.name = name; };使用new關(guān)鍵字創(chuàng)建一個(gè)A的實(shí)例對(duì)象let a = new A();
new關(guān)鍵字主要做了以下幾個(gè)步驟:
(1)創(chuàng)建一個(gè)空的對(duì)象
var obj = {};
(2)將這個(gè)對(duì)象的原型__proto__指向A的prototype
obj.__proto__ = A.prototype
(3)函數(shù)A的this指向obj;接著執(zhí)行A函數(shù)
(4)將obj返回,變量a指向obj
本文主要是參考了別人的文章,寫一些自己的理解,如果有什么寫錯(cuò)的地方歡迎大神來指正一下
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/101767.html
摘要:調(diào)用棧就是為了到達(dá)當(dāng)前執(zhí)行位置所調(diào)用到的所用函數(shù)。方法測試是否至少有一個(gè)元素通過由提供的函數(shù)實(shí)現(xiàn)的測試返回值是終止。然而,如果存在于原型鏈上層,賦值語句的行為就會(huì)有些不同而且可能很出人意料。 typeof null 為 object 解釋 不同的對(duì)象在底層都表示為二進(jìn)制,在JavaScript中二進(jìn)制前三位都為0的話會(huì)被判斷為object類型,null 的二進(jìn)制表示都是0,自然前三位都...
摘要:以上是面試中筆試涉及到的知識(shí)點(diǎn)或者后面被問到的只是點(diǎn)。也許是根據(jù)薪資和面試的等級(jí)來出題的。我剛面試完回家,吃了一個(gè)泡面,回憶下面試題。同時(shí)作為傳遞到構(gòu)造函數(shù),執(zhí)行了一次讓構(gòu)造函數(shù)里面的屬性和方法賦值了一份給。 css 如何水平垂直居中,請(qǐng)盡量多說幾種方法?很尷尬,我多次面試都被問到這個(gè)問題,fuck 定位(回答了)、table-cell布局、flex布局、translate+relat...
摘要:以上是面試中筆試涉及到的知識(shí)點(diǎn)或者后面被問到的只是點(diǎn)。也許是根據(jù)薪資和面試的等級(jí)來出題的。我剛面試完回家,吃了一個(gè)泡面,回憶下面試題。同時(shí)作為傳遞到構(gòu)造函數(shù),執(zhí)行了一次讓構(gòu)造函數(shù)里面的屬性和方法賦值了一份給。 css 如何水平垂直居中,請(qǐng)盡量多說幾種方法?很尷尬,我多次面試都被問到這個(gè)問題,fuck 定位(回答了)、table-cell布局、flex布局、translate+relat...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個(gè)方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進(jìn)的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識(shí)之 HTTP 協(xié)議 詳細(xì)介紹 HTT...
摘要:組合使用構(gòu)造函數(shù)模式和原型。構(gòu)造函數(shù)用于定義實(shí)例屬性,原型鏈用于定定方法和共享的屬性。為了避免矛盾和意外的結(jié)果總是指定基數(shù)參數(shù)。 本文主要記錄平時(shí)開發(fā)遇到的知識(shí)點(diǎn)和小技巧 原型對(duì)象與原型鏈 JavaScritp 引擎在訪問對(duì)象的屬性時(shí),如果在對(duì)象本身中沒有找到,則會(huì)去原型鏈中查找,如果找到,直接返回值,如果整個(gè)鏈都遍歷且沒有找到屬性,則返回 undefined.原型鏈一般實(shí)現(xiàn)為一個(gè)鏈表...
閱讀 1056·2021-11-22 15:35
閱讀 1694·2021-10-26 09:49
閱讀 3238·2021-09-02 15:11
閱讀 2083·2019-08-30 15:53
閱讀 2640·2019-08-30 15:53
閱讀 2926·2019-08-30 14:11
閱讀 3533·2019-08-30 12:59
閱讀 3244·2019-08-30 12:53