JS雖然不是物件導向類型的語言,但這不並不代表JS就不能夠實現OOP的特性。 我相信大家在使用JS的時候,一定有用過Object的原型方法,像是call,apply,hasOwnProperty等等方法,可是這些方法是從哪裡來的呢?如果JS無法實作繼承的話,這些方法的使用就無從談起了。這裡我們就來談談在JS實現繼承的方法,原型鏈。
_proto_和prototype
首先我們要了解什麼是普通對象,什麼是函數物件。
普通物件
#var a = {}
#var a = new Object();
var a = new f1();//與上一個建立物件的方式相同
函數物件
var a = function(){};
var a = new Function() {};
f1()
#_proto_是每個普通物件都擁有的屬性,用來指向建構函數的prototype,也就是建構函式的原型物件。而建構子的原型物件一般來說也是一個普通物件(在建構子是Function的時候,它就變成了一個函數物件),所以它也有_proto_屬性。而它的_proto_則指向它的建構子的原型對象,也就是Object.prototype。最後的Object.prototype._proto_指向null,到了原型鏈的頂端。
prototype是函數物件都擁有的屬性,它在物件建立的時候被指定給新的物件實例。當然也可以動態修改。
function Person(){}; var p = new Person();//创建一个普通对象 //创建过程实际为 var p={}; p._proto_=Person.prototype; Person.apply(p,arguments);//或者是call... //执行构造函数,并返回创建的对象。
對上面程式碼的補充說明
正常來講建構函式中是不用寫return語句的,因為它會預設回傳新建立的物件。但是,如果在建構函式中寫了return語句,如果return的是一個對象,那麼函數就會覆寫新建立的對象,而傳回此物件;如果return的是基本型別如字串、數字、布林值等,那麼函數會忽略掉return語句,還是傳回新建立的物件。
而建構函數的原型物件的預設值為:
Person.prototype={ constructor://指向构造函数本身 _proto_://指向构造函数Person的原型对象的构造函数的原型对象,这里是指Object.prototype } //这里有一个特殊情况——当构造函数为Function的时候 Function.prototype._proto_===Object.prototype //我们知道Function.prototype是一个函数对象,它的_proto_应该指向它的构造函数的原型,也就是Function.prototype。 //可是这样下去就没完没了了,毕竟一条链总是有顶端的。这里约定Function.prototype._proto_===Object.prototype; //这时,Object.prototype._proto_===null;完美结束原型链。
我們可以不斷修改建構子的原型物件的指向,這樣最終就可以形成一條鏈。而上面提到的一條鏈就是JS中的預設原型鏈。
談談程式碼實作
下面我們來看看程式碼:
function Parent(name){ this.name=name||"parent"; } function Son(name){ this.name=name||"son"; this.property="initial Son name"; } function Grandson(name){ this.name=name||"grandson"; this.ggs="initial Grandson name"; } Son.prototype = new Parent("原型中的Parent"); Grandson.prototype = new Son("原型中的Son"); let grandson = new Grandson("孙子"); console.log(grandson instanceof Son);//true console.log(grandson instanceof Grandson);//true console.log(grandson instanceof Parent);//true
很顯然,最後都會輸出true。但是我們改動一點程式碼:
Grandson.prototype = new Son("原型中的Son"); Son.prototype = new Parent("原型中的Parent");//其实上一步已经实例化了一个Son的对象给Grandson.prototype //这个时候Son的实例的_proto_已经确定指向那个时候的构造函数.prototype了(默认原型对象) let grandson = new Grandson("孙子"); console.log(grandson instanceof Son);//false console.log(grandson instanceof Grandson);//true console.log(grandson instanceof Parent);//false
為什麼結果會改變呢?原因也很簡單。我們之前有提到物件的創建的創建過程:物件在實例化的時候就已經給物件的_proto_賦了建構子的prototype了。也就是說上面程式碼中第一行已經確定了Grandson.prototype._proto_的值了,即使在第二行修改了Son.prototype也是無法修改Grandson.prototype._proto_的值。
Conclusion:JS中原型鏈的關係是由_proto_維持的,而不是prototype。
小測驗
var animal = function(){}; var dog = function(){}; animal.price = 2000; dog.prototype = animal; var tidy = new dog(); console.log(dog.price) console.log(tidy.price)
答案是輸出什麼呢?是undefined和2000,我們分析一下:
首先我們清楚animal和dog都是函數對象,在第四行修改了dog的原型對象為animal。那我們接著往下看,console.log(dog.price)
這句話首先會尋找dog的price,沒有。然後到原型鏈上尋找。怎麼找的呢?我們之前提到是透過_proto_去到它建構函數的原型物件上,這裡因為dog是函數對象,那麼它的建構函式的原型物件就是Function.prototype,這是一個empty function。於是回傳undefined,沒有找到price這個屬性。
那麼console.log(tidy.price)
呢?
tidy是一個普通對象,首先也是尋找它本身的屬性price,也沒有。透過_proto_去到它建構函式的原型物件上,也就是dog.prototype。因為tidy實例化在dog.prototype = animal;
之後,所以tidy._proto_的指向已經指向了修改後的dog.prototype。也就是指向了animal,也就是能夠找到price這個屬性了,所以輸出2000。
原型物件上的所有屬性和方法都可以看成是Java中父類別的public(protected)屬性和方法,在這些方法內部使用this即可存取建構函式中的屬性和方法。至於為什麼,這又得提到JS中this的綁定問題了….總而言之,誰調用的函數,this就指向誰。箭頭函數除外…
相關建議:
以上是JS中的原型鏈詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

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

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

WebStorm Mac版
好用的JavaScript開發工具

Dreamweaver CS6
視覺化網頁開發工具