摘要:屬性這是每個對象都有的隱式原型屬性,指向了創建該對象的構造函數的原型。
原型
在JavaScript中,有兩個原型,分別是 prototype 和 _proto_
注:在ECMA-262第5版中管這個 _proto_ 叫 [[Prototype]]
prototype 屬性:
這是一個顯式原型屬性,只有函數才擁有該屬性。
_proto_ 屬性:
這是每個對象都有的隱式原型屬性,指向了創建該對象的構造函數的原型。
創建函數有兩種方式:
①、通過 function 關鍵字定義
②、通過 new Function
其中函數又可以分為普通函數和構造函數,兩者唯一的區別就是調用的方式不同,語法上沒有差異
function normalFn(){} // 普通函數(函數名首字母小寫) function StructFn(){} // 構造函數(函數名首字母大寫)
創建對象的方式多種多樣,其中傳統方法是通過構造函數來創建對象,使用 new 關鍵字即可創建,創建出來的對象實例可通過 constructor 來訪問構造函數
let obj = new StructFn() // obj就是一個對象 console.log(obj.constructor) // function normalFn(){}
在JS中,萬物都是對象,函數也屬于對象,只不過函數相對于對象有著更為精確的定義
原型初探為了證明 prototype屬性 是函數獨有,而__proto__是每個對象都有的,我們可以測試以下代碼:
function a(){} console.log(a.prototype); // {constructor: ?} console.log(a.__proto__); // ? () { [native code] } let obj = new Object() console.log(obj.prototype) // undefined console.log(obj.__proto__) // {constructor: ?, __defineGetter__: ?, ?…}
可以看到對象的 顯式原型(prototype)為undefined
*注意:
undefined 和 null 同屬于對象,但是它們都沒有原型,為什么? 在JavaScript中,目前只有兩個只有一個值的數據類型,那就是 undefined 和 null*
由于這兩種數據類型有且只有一個值,并且沒有方法,所以自然而然就沒有原型了。
有的同學會問,那NaN呢?NaN是屬于Number數據類型的,屬于對象,只有_proto_ 屬性
console.log(undefined.__proto__); // 報錯:Uncaught TypeError: Cannot read property "__proto__" of undefined console.log(null.__proto__); // 報錯:Uncaught TypeError: Cannot read property "__proto__" of null console.log(NaN.__proto__) ; // Number?{0, constructor: ?, toExponential: ?, ?…}構造函數創建對象,其中發生什么?
1.創建了一個新對象 2.將新創建的對象的隱式原型指向其構造函數的顯式原型。 3.將this指向這個新對象 4.返回新對象
注意看第二條:將新創建的對象的隱式原型指向其構造函數的顯式原型
也就是說 對象.__prototype === 構造函數.prototype
function fn(){} let obj = new fn(); console.log(obj.__proto__ === fn.prototype); // true
那么這樣,我們在為構造函數添加原型方法時,就可以通過兩種方法取訪問了
fn.prototype.more = function(){console.log("fn-prototype-more")} // 1、通過構造函數的顯式原型 fn.prototype.more() // 2、通過對象的隱式原型 obj.__proto__.more()原型鏈
原型鏈:實例與原型之間的鏈接
先來看一個例子:
function Abc(){} Abc.prototype.fn = function(){console.log("Abc-prototype-fn")}; let obj = new Abc() obj.fn() // Abc-prototype-fn
從上面的代碼我們可以看到。構造函數 Abc 和對象實例 obj 都沒有fn這個方法,之所以對象obj能夠訪問到Abc的原型方法,是通過原型鏈來尋找,借用了 _proto_ 這個屬性
所以以下的代碼也是等價的
obj.fn() // Abc-prototype-fn obj.__proto__.fn() // Abc-prototype-fn
再來看一個復雜的例子:
function Abc(){ this.fn = function(){console.log("Abc-fn")}; } Abc.prototype.fn = function(){console.log("Abc-prototype-fn")}; Object.prototype.fn = function(){console.log("Object-fn")}; let obj = new Abc() obj.fn = function(){console.log("obj-fn")}; obj.fn()
這里有4個重名的fn函數,分別是:
①、實例對象obj的方法
②、構造函數Abc的方法
③、構造函數Abc原型上的方法
④、Obecjt對象原型上的方法
為了表示方法的尋找過程,我畫了一幅很丑陋的圖,大家不要介意哈!
在尋找某個方法或者屬性的時候,會先從自身對象尋找;
如果沒有,則會去構造函數尋找;注意這里還沒用到原型鏈;
緊接著,會到構造函數的原型上尋找,此時就是對象Abc通過 _proto_ 屬性進行尋找
接下來,會到Object對象的原型尋找,Object對象是所有對象之父,可以說所有的對象都繼承了Object,此時構造函數通過_proto_ 屬性找到了Object的prototype
最后的最后,由于Object._proto_ 指向了null,這也就是原型鏈的末端
第一道原型鏈是 obj._proto_ ,訪問到了Abc的prototype
console.log(obj.__proto__ === Abc.prototype) // true
第二道原型鏈是 obj.__proto__.__proto__ ,訪問到了Object的prototype
console.log(obj.__proto__.__proto__ === Object.prototype) //true
第三道原型鏈是 obj.__proto__.__proto__.__proto__ 訪問到了Object的prototype.__proto__,,最后指向了null
console.log(obj.__proto__.__proto__.__proto__ === null) //true
這樣我們就可以看到了整個原型鏈的流程了
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101531.html
摘要:寄生組合式繼承終于寫到最后一個繼承了,我們在之前講了種繼承方式,分別是原型鏈,借用構造函數繼承,組合繼承,原型式繼承,寄生式繼承,其中,前三種聯系比較緊密,后面兩種也比較緊密,而我們要講的最后一種,是和組合繼承還有寄生式繼承有關系的。 前言 趁周末結束之前趕緊先把坑填上。上回我們說到了原型鏈,并且留下了幾個思考題,先把答案公布一下。 在最后一個例子里,console.log(b1.c...
摘要:我們通過一個簡單的例子與圖示,來了解構造函數,實例與原型三者之間的關系。而原型對象的指向構造函數。于是根據構造函數與原型的特性,我們就可以將在構造函數中,通過聲明的屬性與方法稱為私有變量與方法,它們被當前被某一個實例對象所獨有。 showImg(https://segmentfault.com/img/remote/1460000008593382); 如果要我總結一下學習前端以來我遇...
摘要:為了防止之后自己又開始模糊,所以自己來總結一下中關于作用域鏈和原型鏈的知識,并將二者相比較看待進一步加深理解。因此我們發現當多個作用域相互嵌套的時候,就形成了作用域鏈。原型鏈原型說完了作用域鏈,我們來講講原型鏈。 畢業也整整一年了,看著很多學弟都畢業了,忽然心中頗有感慨,時間一去不復還呀。記得從去年這個時候接觸到JavaScript,從一開始就很喜歡這門語言,當時迷迷糊糊看完了《J...
摘要:我們用一張圖表示構造函數和實例原型之間的關系好了構造函數和實例原型之間的關系我們已經梳理清楚了,那我們怎么表示實例與實例原型,也就是或者和之間的關系呢。 開篇: 在Brendan Eich大神為JavaScript設計面向對象系統的時候,借鑒了Self 和Smalltalk這兩門基于原型的語言,之所以選擇基于原型的面向對象系統,并不是因為時間匆忙,它設計起來相對簡單,而是因為從一開始B...
摘要:我們用一張圖表示構造函數和實例原型之間的關系好了構造函數和實例原型之間的關系我們已經梳理清楚了,那我們怎么表示實例與實例原型,也就是或者和之間的關系呢。 開篇: 在Brendan Eich大神為JavaScript設計面向對象系統的時候,借鑒了Self 和Smalltalk這兩門基于原型的語言,之所以選擇基于原型的面向對象系統,并不是因為時間匆忙,它設計起來相對簡單,而是因為從一開始B...
閱讀 3762·2021-11-24 09:39
閱讀 2964·2021-11-16 11:49
閱讀 2081·2019-08-30 13:54
閱讀 1107·2019-08-30 13:03
閱讀 1096·2019-08-30 11:10
閱讀 721·2019-08-29 17:10
閱讀 1252·2019-08-29 15:04
閱讀 1218·2019-08-29 13:02