這篇文章主要介紹了JavaScript中的原型prototype完全解析,prototype可是js界"一切皆對象"論調的重要支撐,講解了__proto__屬性和原型鍊等乾貨,需要的朋友可以參考下
要理解JS中的prototype, 首先必須弄清楚以下幾個概念
1. JS中所有的東西都是物件
2. JS中所有的東西都由Object衍生而來, 即所有東西原型鏈的終點指向Object.prototype
// ["constructor", "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", // "propertyIsEnumerable", "__defineGetter__", "__lookupGetter__", "__defineSetter__", // "__lookupSetter__"] console.log(Object.getOwnPropertyNames(Object.prototype));
3. JS中建構子與實例(物件)之間的微妙關係
建構函數透過定義prototype來約定其實例的規格, 再透過new 來建構出實例, 他們的作用就是生產物件.
而建構函數(方法)本身又是方法(Function)的實例, 因此也可以查到它的__proto__(原型鏈)
Object / function F() {} 這樣子的是建構子囉, 一個是JS原生API提供的, 一個是自訂的
new Object() / new F( 實例啦
實例就"只能"查看__proto__來得知自己是基於什麼prototype被製造出來的,
而"不能"再重新定義實例的prototype妄想創造出實例的實例了.
實踐出真知, 只有自己動手觀察/思考才能真正領悟:
// 先来看看构造函数到底是什么 // function Empty() {} function Empty() {} console.log(Function.prototype, Function.__proto__); // Object {} function Empty() {} console.log(Object.prototype, Object.__proto__); function F() {} // F {} function Empty() {} console.log(F.prototype, F.__proto__);
你可能已經暈了, 我們來分解一下。
prototype prototype輸出的格式為: 建構函式名稱原型
先看下Object.prototype輸出了什麼?
Object {} -> 前面的Object為建構函數的名稱, 後面的那個表示原型, 這裡是一個{}, 即一個Object對象的實例(空對象)
那麼F {} 我們就明白是什麼意思了, F 就是構造函數的名稱, 原型也是一個空物件
// 再来看看由构造函数构造出来的实例 var o = new Object(); // var o = {}; // undefined Object {} console.log(o.prototype, o.__proto__); function F() {} var i = new F(); // undefined F {} console.log(i.prototype, i.__proto__);
我們再深入一點, 定義下F 的原型看看到底會發生些什麼?
function F() {} F.prototype.a = function() {}; var i = new F(); // undefined F {a: function} console.log(i.prototype, i.__proto__);
這樣我們就清楚的看到i 是由F 建構出來的,原型是{a: function}, 是原本的空物件原型新增了一個a 方法
我們再換一個狀況, 完全覆寫F 的原型會怎麼樣?
function F() {} F.prototype = { a: function() {} }; var i = new F(); // undefined Object {a: function} console.log(i.prototype, i.__proto__);
咦~ 為什麼這裡表明i 是由Object 建構出來的? 不對吧!
因為我們完全將F 的prototype覆蓋, 其實也就是將原型指定為物件{a: function}, 但這會造成原本的constructor訊息遺失, 變成了物件{a: function}指定的constructor.
那麼物件{a: function}的constructor是什麼呢?
因為物件{a: function}其實就相對於
var o = {a: function() {}} // new了一个Object
那麼o的constructor當然是Object 啦
我們來修正下這個錯誤
function F() {} F.prototype = { a: function() {} } // 重新指定正确的构造函数 F.prototype.constructor = F; var i = new F(); // undefined F {a: function, constructor: function} console.log(i.prototype, i.__proto__);
現在又能得到正確的原型資訊了~
現在又能得到正確的原型資訊了~
原型鏈
然後來看看什麼原型鏈又是個什麼東西?
簡單的來講和OOP中的繼承關係(鏈)是一樣的, 一層一層往上找, 直至最終的Object.prototype
最關鍵的是要弄清楚JS中哪些東西是(實例)物件, 這個簡單了, JS中所有東西都是物件! 再來弄清楚就是任何一個物件都是有原型的!
那麼我們來證明一下:
Object // 这是一个函数, 函数是 Function 的实例对象, 那么就是由 Function 构造出来的 Object.__proto__ == Function.prototype // 那么Object的原型, true // 这个是一个普通对象了, 因此属于 Object 的实例 Function.prototype.__proto__ == Object.prototype // true // 这已经是原型链的最顶层了, 因此最终的指向 null Object.prototype.__proto__ == null // true Function // 这也是一个函数, 没错吧! Function.__proto__ == Function.prototype // true function A() {} // 这是一个自定义的函数, 终归还是一个函数, 没错吧! A.__proto__ == Function.prototype // 任何函数都是 Function 的实例, 因此A的原型是? var a = new A() a.__proto__ == A.prototype // 实例a是由A构造函数构造出来的, 因此a的原型是由A的prototype属性定义的 A.prototype.__proto__ == Object.prototype // 普通对象都是 Object 的示例
Prototype和__proto__
每一個物件都包含一個__proto__,指向這個的物件的「原型」。類似的事情是,每一個函數都包含一個prototype,這個prototype物件幹什麼的了?
function Foo(){}; var foo = new Foo(); console.log(foo.__proto__);試想想,這個foo物件的__proto__會指向什麼?
function Foo(){}; var foo = new Foo(); console.log(foo.__proto__); console.log(Foo.prototype); console.log(foo.__proto__ === Foo.prototype);
原來,new出來的物件foo的__proto__就只指向函數Foo的prototype。
foo.__proto__ --> Foo.prototype###JS這麼設計有何意義了?回憶下上面說的,在JS的世界中,物件不是根據類別(模具)創建出來的,而是從原型(另一個物件)衍生出來的。 ######當我們執行new操作建立一個新的物件時,先不深入new操作的具體實現,但有一點我們是肯定的-就是為新物件的__proto__指向一個原型物件。 ######就剛才這段程式碼###
function Foo(){}; var foo = new Foo();
foo.__proto__到底要指向谁了?你怎么不能指向Foo这个函数本身吧,虽然函数也是对象,这个有机会会详细讲。但如何foo.__proto__指向Foo固然不合适,因为Foo是一个函数,有很多逻辑代码,foo作为一个对象,继承逻辑处理没有任何意义,它要继承的是“原型对象”的属性。
所以,每个函数会自动生成一个prototype对象,由这个函数new出来的对象的__proto__就指向这个函数的prototype。
foo.__proto__ --> Foo.prototype
总结说了这么多,感觉还是没完全说清楚,不如上一张图。我曾经参考过其他网友的图,但总觉得哪里没说清楚,所以我自己画了一张图,如果觉得我的不错,请点个赞!(老子可是费了牛劲才画出来)。
咱们就着这张图,记住如下几个事实:
1. 每个对象中都有一个_proto_属性。
JS世界中没有类(模具)的概念,对象是从另一个对象(原型)衍生出来的,所以每个对象中会有一个_proto_属性指向它的原型对象。(参考左上角的那个用字面量形式定义的对象obj,它在内存中开辟了一个空间存放对象自身的属性,同时生成一个_proto_指向它的原型——顶层原型对象。)
2. 每个函数都有一个prototype属性。
“构造函数”为何叫构造函数,因为它要构造对象。那么根据上面第一条事实,构造出来的新对象的_proto_属性指向谁了?总不能指向构造函数自身,虽然它也是个对象,但你不希望新对象继承函数的属性与方法吧。所以,在每个构造函数都会有一个prototype属性,指向一个对象作为这个构造函数构造出来的新对象的原型。
3. 函数也是对象。
每个函数都有一些通用的属性和方法,比如apply()/call()等。但这些通用的方法是如何继承的呢?函数又是怎么创建出来的呢?试想想,一切皆对象,包括函数也是对象,而且是通过构造函数构造出来的对象。那么根据上面第二条事实,每个函数也会有_proto_指向它的构造函数的prototype。而这个构造函数的函数就是Function,JS中的所有函数都是由Function构造出来的。函数的通用属性与方法就存放在Function.prototype这个原型对象上。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
全面分析JavaScript面向对象概念中的Object类型与作用域(附有示例)
详细解读JavaScript设计模式开发中的桥接模式(高级篇)
以上是在JavaScript中對原型prototype全面分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Dreamweaver Mac版
視覺化網頁開發工具

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

WebStorm Mac版
好用的JavaScript開發工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中