搜尋
首頁web前端js教程javascript 原型鏈維護與繼承詳解_javascript技巧

一.兩個原型

很多人都知道javascript是原型繼承,每個建構函式都有一個prototype成員,透過它就可以把javascript的繼承演義的美輪美奐了.
其實啊,光靠這一個屬性是無法完成javascript的繼承.
我們在程式碼中使用的prototype完成繼承在這裡就不多說了.大家可以查一下資料.
另外一個看不見的prototype成員.
每一個實例都有有一條指向原型的prototype屬性,這個屬性是無法被訪問到的,當然也就無法被修改了,因為這是維護javascript繼承的基礎.

複製程式碼 程式碼如下:

//建構器宣告
        function Guoyansi(){ }
        function GuoyansiEx(){}
        //原型繼承
         GuoyansiEx.prototype=new Guoyansi();
       //建立物件
       var g1=new GuoyansiEx();
       var g2=new GuoyansiEx();

上面的程式碼中的物件可以用下面的圖來說明

二.原型的維護

一個構造器產生的實例,其constructor屬性總是指向該構造器.我們暫且認為該話是對的.

複製程式碼 程式碼如下:

function Guoyansi(){ }
var obj1=new Guoyansi();
console.log(obj1.constructor===Guoyansi);//true

其實構造器本身是沒有constructor這個屬性的,那麼這個屬性是來自哪呢?
答案是:來自原型.
因此得出下面的結論

複製程式碼 程式碼如下:
obj1.constructor===Guoyansi.prototype.consi.

既然我們可以透過constructor來尋找構造器.因此我們就可以進一步完善上面的圖了.

複製程式碼 程式碼如下:

 function GuoyansiEx(){}
             GuoyansiEx.prototype=new Guoyansi();
             console.log(GuoyansiEx.constructor===GuoyansiEx)//false

根據上圖,上面的結果應該是true,但為什麼是false呢?

現在做個分析.
GuoyansiEx的原型被Guoyansi的實例重寫了,那麼GuoyansiEx的原型中的constructor自然也是來自Guoyansi的實例.
而Guoyansi實例中的constructor又是來自Guoyansi.prototype.而Guoyansi.prototype沒有被重寫,
所以Guoyansi.prototype的constructor指向Guoyansi(建構子);

根據上述分析得出下面的結論

複製程式碼 程式碼如下:
GuoyansiEx.constructor===Guoyansi.constructor===Guoyansi; 🎜>
如果在開發過程中對於Constructor的指向要求非常精確的話,可以做如下處理.

複製程式碼 程式碼如下:
/**方法一:**/
 function Guoyansi(){}
             function GuoyansiEx(){}
             GuoyansiEx.prototype=new Guoyansi();
             GuoyansiEx.prototype.constructor=GuoyansiEx;//重置constructor指向.

複製程式碼 程式碼如下:

/**
            方法二
            **/
            function Guoyansi(){}
            function GuoyansiEx(){
                this.constructor=arguments.callee;
            }
            GuoyansiEx.prototype=new Guoyansi();

複製程式碼 程式碼如下:

/**
            方法三
            **/
            function Guoyansi(){}
            function GuoyansiEx(){
                this.constructor=GuoyansiEx;
            }
            GuoyansiEx.prototype=new Guoyansi();

三.看不見的原型有什麼用呢?

看得見的原型鏈我們可以對他操作來完成我們的繼承,那麼這個看不見的原型鏈我們既看不見,又無法操作.要它有何用.
物件導向中繼承有一個特性:相似性.子類別與父類別具有相似性.因此在子類別中你是無法用delete刪除從父類別繼承而來的成員.也就是說子類別必須具有父類別的特性.
為了維護這個特性,javascript在物件的內部產生了一條我們看不見的原型屬性,並且不允許使用者存取.這樣,使用者可以處於任何目的來修改constructor,
而不會破壞子類別擁有父類別的特性.
簡而言之:內部原型是javascript的原型繼承機制所需要的,而外部原型是用戶實現繼承所需要的.

四.火狐引擎SpiderMonkey中的__proto__

還是這段程式碼.

複製程式碼 程式碼如下:

function Guoyansi(){}
            Guoyansi.prototype.age=24;
            function GuoyansiEx(){}
            var obj1=new Guoyansi();
            GuoyansiEx.prototype=obj1;
            GuoyansiEx.prototype.constructor=GuoyansiEx;//重置constructor指向.
            var obj2=new GuoyansiEx();

我現在想要從obj開始向上訪問父類Guoyansi的prototype的屬性的age.
思路是這樣的.
第一步:obj2====>obj2.constructor.prototype
第二部:obj2.constructor.prototype===>GuoyansiEx.prototype;
第三部:GuoyansiEx.prototype===>obj1;
第四部:obj1.constructor====>Guoyansi
第五部:Guoyansi.prototype.age

寫成這樣:console.log(obj2.constructor.prototype.constructor.prototype.age)//24;
最終的結果是24.
最終的結果是24.可以正常執行,但是在好多書上說constructor修改後,級無法在找到父類中的原型了.不知道是怎麼回事.

在火狐中提夠了一種更簡潔的屬性._proto_
SpiderMonkey中預設在任何建立的物件上新增了一個名為_proto_的屬性,該屬性指向建構器所使用的原型.
其實就是我們上面提到的不可見的原型鏈,只不過是在這個地方變相的公開而已.
可以這樣存取到age
console.log(obj2.__proto__.__proto__.age);//24
這樣的確是成功的訪問到了父類的原型屬性,但是這個屬性只適用於火狐,在其他瀏覽器中是會出錯的.
在E5中對Object做出了擴充Object.getPrototypeOf(),可以存取到所有父類別的原型了.

複製程式碼 程式碼如下:

function Guoyansi(){}
            Guoyansi.prototype.age=24;
            function GuoyansiEx(){}
            var obj1=new Guoyansi();
            GuoyansiEx.prototype=obj1;
            GuoyansiEx.prototype.constructor=GuoyansiEx;//重置constructor指向.
            var obj2=new GuoyansiEx();
            var proto=Object.getPrototypeOf(obj2);
            while(proto){
                console.log(proto.constructor);
                proto=Object.getPrototypeOf(proto);
            }
            console.log("object的原型" proto);

結果是:GuoyansiEx
Guoyansi
Object
object的原型null

個人覺得這些應該算是javascript面向對象的精髓之一了.小伙伴們自己參考下,根據需求使用到自己的項目中去吧

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱工具

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。