javascript
关于javascript的原型和原型链,看我就够了(二)
溫故
創(chuàng)建對(duì)象的三種方式
- 通過(guò)對(duì)象直接量
- 通過(guò)new創(chuàng)建對(duì)象
- 通過(guò)Object.create()
js中對(duì)象分為兩種
- 函數(shù)對(duì)象
- 普通對(duì)象 仔細(xì)觀察如下代碼
綜合以上,得出結(jié)論==>普通對(duì)象都是通過(guò)函數(shù)創(chuàng)建的
prototype
每一個(gè)函數(shù)對(duì)象都有一個(gè)prototype屬性,但是普通對(duì)象是沒(méi)有的;
遺留問(wèn)題
昨天留下了一些知識(shí)點(diǎn),今天重點(diǎn)討論
- constructor
- _proto_
知新
constructor構(gòu)造函數(shù)
我們昨天說(shuō)創(chuàng)建對(duì)象的三種方式,第二種是通過(guò)new創(chuàng)建對(duì)象,
var obj = new Object()//創(chuàng)建一個(gè)空對(duì)象等同于 var obj = {} console.log(obj.constructor===Object)//true 復(fù)制代碼Object就是一個(gè)構(gòu)造函數(shù),是js內(nèi)置的構(gòu)造函數(shù),上面的例子中Object就是obj的構(gòu)造函數(shù),這個(gè)例子似乎不太明顯,我們繼續(xù)看
function Foo(name){this.name = name } var foo = new Foo("陌上寒") console.log(foo.constructor===Foo)//true 復(fù)制代碼我們自定義了一個(gè)構(gòu)造函數(shù)Foo,Foo是foo的構(gòu)造函數(shù),foo的構(gòu)造函數(shù)就是Foo 構(gòu)造函數(shù)與其他函數(shù)的唯一區(qū)別,就在于調(diào)用它們的方式不同。不過(guò),構(gòu)造函數(shù)畢竟也是函數(shù),不存在定義構(gòu)造函數(shù)的特殊語(yǔ)法。任何函數(shù),只要通過(guò) new 操作符來(lái)調(diào)用,那它就可以作為構(gòu)造函數(shù);而任何函數(shù),如果不通過(guò) new 操作符來(lái)調(diào)用,那它跟普通函數(shù)也不會(huì)有什么兩樣。 構(gòu)造函數(shù)在創(chuàng)建時(shí)有一個(gè)約定,如果是構(gòu)造函數(shù),那么首字母要大寫(xiě),普通函數(shù)首字母小寫(xiě)
constructor和prototype
constructor和我們昨天討論的prototype有什么聯(lián)系嗎? 觀察如下代碼的輸出
function Foo(name) {this.name = name; } var foo = new Foo('陌上寒'); console.log(Foo.prototype) 復(fù)制代碼通過(guò)昨天的討論我們得知只有函數(shù)對(duì)象才存在prototype 輸出
Foo.prototype是Foo的原型對(duì)象 繼續(xù)觀察 function Foo(name) {this.name = name; } var foo = new Foo('陌上寒');console.log(Foo.prototype.constructor===Foo)//true 復(fù)制代碼在默認(rèn)情況下,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè) constructor(構(gòu)造函數(shù))屬性,這個(gè)屬性包含一個(gè)指向 prototype 屬性所在函數(shù)的指針。就拿前面的例子來(lái)說(shuō),Foo.prototype.constructor 指向 Foo。 我們得出以下結(jié)論 原型對(duì)象中的constructor屬性,指向該原型對(duì)象對(duì)應(yīng)的構(gòu)造函數(shù) 也就是說(shuō)上面的例子,Foo的原型對(duì)象是Foo.prototype,原型對(duì)象(Foo.prototype)中有一個(gè)constructor屬性,這個(gè)constructor屬性指向原型對(duì)象(Foo.prototype)對(duì)應(yīng)的構(gòu)造函數(shù)Foo,用一行代碼概括
console.log(Foo.prototype.constructor===Foo)//true 復(fù)制代碼以上就是constructor和prototype的關(guān)系 我們注意到原型對(duì)象(Foo.prototype)中還存在一個(gè)屬性_proto_,這又是什么?它和prototype,constructor又有什么關(guān)聯(lián)呢?
隱式原型(_proto_)
那么__proto__是什么?每個(gè)對(duì)象都會(huì)在其內(nèi)部初始化一個(gè)屬性,就是_proto_。 Firefox、Safari 和 Chrome 的每個(gè)對(duì)象上都有這個(gè)屬性 ,而在其他瀏覽器中是完全不可見(jiàn)的(為了確保瀏覽器兼容性問(wèn)題,不要直接使用 _proto_ 屬性,此處只為演示)。我們繼續(xù)看代碼
var arr = new Array() console.log(arr.__proto__===Array.prototype);//true var str = new String() console.log(str.__proto__===String.prototype);//true var Fun = new Function() console.log(Fun.__proto__===Function.prototype);//true var bool = new Boolean console.log(bool.__proto__===Boolean.prototype);//true var obj = new Object() console.log(obj.__proto__===Object.prototype);//true function MyFun() {console.log("我是陌上寒"); } var myfoo = new MyFun() console.log(myfoo.__proto__===MyFun.prototype);//true 復(fù)制代碼再重復(fù)一次:Array,String,Function,Boolean,Object都是js內(nèi)置的構(gòu)造函數(shù),MyFun是自定義的構(gòu)造函數(shù) 只有函數(shù)對(duì)象才存在prototype 所有對(duì)象(除了Object.prototype)都存在_proto_ 剛才我們討論過(guò),普通對(duì)象都是通過(guò)函數(shù)創(chuàng)建的 根據(jù)以上我們得出結(jié)論: 普通對(duì)象__proto__指向當(dāng)前函數(shù)對(duì)象的原型, 你可能發(fā)現(xiàn)了,有一個(gè)矛盾的地方,所有對(duì)象都存在_proto_,只有普通對(duì)象的__proto__指向當(dāng)前函數(shù)對(duì)象的原型,那函數(shù)對(duì)象的__proto__指向哪里呢?繼續(xù)看代碼
function MyFun() {console.log("我是陌上寒"); } console.log(Boolean.__proto__);//? () { [native code] } console.log(Function.__proto__);//? () { [native code] } console.log(String.__proto__);//? () { [native code] } console.log(Array.__proto__);//? () { [native code] } console.log(Object.__proto__);//? () { [native code] } console.log(MyFun.__proto__);//? () { [native code] } 復(fù)制代碼函數(shù)對(duì)象的__proto__輸出的都是? () { [native code] } 函數(shù)內(nèi)部是[native code],也就是系統(tǒng)編譯好的二進(jìn)制代碼函數(shù),我們不對(duì)此做研究 上面說(shuō)到,所有對(duì)象都有_proto_,原型對(duì)象也是對(duì)象, 我們得出結(jié)論 原型對(duì)象也存在_proto_ 結(jié)合以上我門又一次得出結(jié)論 原型對(duì)象的__proto__指向當(dāng)前函數(shù)對(duì)象的原型, 還是繼續(xù)看代碼,便于理解*
console.log('陌上寒'.__proto__===String.prototype);//true console.log(String.prototype.__proto__===Object.prototype);//true //等量代換,得出一下結(jié)論 console.log('陌上寒'.__proto__.__proto__===Object.prototype);//true //自此形成了一條鏈,===>原型鏈 復(fù)制代碼解釋一下如上代碼, '陌上寒'是字符串類型,'陌上寒'的構(gòu)造函數(shù)是String(), 所以'陌上寒'的__proto__指向String的原型 String()是js的內(nèi)置構(gòu)造函數(shù),繼承自O(shè)bject,也就是說(shuō)Object是頂端,是原型鏈的頂端,既然是頂端,所以:
console.log(Object.prototype.__proto__)//null 復(fù)制代碼Object的原型對(duì)象是不存在__proto__的
總結(jié)
所有對(duì)象(不包括Object.prototype)有__proto__屬性,函數(shù)對(duì)象有prototype屬性; 對(duì)象由函數(shù)生成; 生成對(duì)象時(shí),對(duì)象的__proto__屬性指向當(dāng)前函數(shù)的prototype屬性。 Object.prototyp處于原型鏈的頂端,不存在原型,不繼承任何屬性,其他原型對(duì)象都是普通對(duì)象,普通對(duì)象都具有原型,所有的內(nèi)置構(gòu)造函數(shù)(以及大部分自定義構(gòu)造函數(shù))都具有一個(gè)繼承自O(shè)bject.prototype的原型,例如Date.prototype的 屬性繼承自O(shè)bject.prototype,因此有new Date()創(chuàng)建的Date對(duì)象的屬性同時(shí)繼承自Date.prototype和Object.prototype,這一系列的原型對(duì)象就是所謂的原型鏈。
原文鏈接
關(guān)于javascript的原型和原型鏈,看我就夠了(一)
參考鏈接 《JavaScript 闖關(guān)記》之原型及原型鏈
JavaScript之原型與原型鏈
一篇文章帶你理解原型和原型鏈
徹底理解JavaScript原型鏈(一)—__proto__的默認(rèn)指向
圖解prototype、proto和constructor的三角關(guān)系
Object.prototype 原型和原型鏈
三張圖搞懂JavaScript的原型對(duì)象與原型鏈
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的关于javascript的原型和原型链,看我就够了(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 多线程基础(一)
- 下一篇: 解析JavaScript中的字符串类型与