Javascript原型钩沉
寫在前面的總結:
JS當中創(chuàng)建一個對象有好幾種方式,大體上就是以下幾種:
①通過var obj ={...}
這種方式一般稱為字面量方式,{}直接寫需要定義的字段
②var obj = new Object()
Object對象是JS的內(nèi)建對象
③通過構造函數(shù)創(chuàng)建對象
例如:
function father(){ this.name = "I'm your father!" } var f = new father();這里通過構造函數(shù)的方式創(chuàng)建了一個對象實例f
④通過Object.create創(chuàng)建對象
Object.create(proto [, propertiesObject ]) 是E5中提出的一種新的對象創(chuàng)建方式,第一個參數(shù)是要繼承的原型,如果不是一個子函數(shù),可以傳一個null,第二個參數(shù)是對象的屬性描述符,這個參數(shù)是可選的。
?
1.原型是什么?
首先應該知道我們創(chuàng)建的每一個函數(shù)都有一個prototype屬性,這個屬性是一個指向原型對象的指針,這個原型對象的用途是包含由特定類型所有實例共享的屬性和方法。
也就是說,每創(chuàng)建一個函數(shù),就會創(chuàng)建一個對應的原型對象。
一個對象的真正原型是被對象內(nèi)部的[[Prototype]]屬性(property)所持有。ECMA引入了標準對象原型訪問器Object.getPrototype(object),到目前為止只有Firefox和chrome實現(xiàn)了此訪問器。除了IE,其他的瀏覽器支持非標準的訪問器__proto__,如果這兩者都不起作用的,我們需要從對象的構造函數(shù)中找到的它原型屬性。?
還是挺抽象,舉個例子吧:
function Person(){this.name="大橙子";this.age = 26;this.sex = "純爺們"; }var p = new Person();console.log(p.name); console.log(p.age); console.log(p.sex); console.log(p.career);Person.prototype.career = "程序員"; console.log(p.career);輸出結果: [Web瀏覽器] "大橙子" [Web瀏覽器] "26" [Web瀏覽器] "純爺們" [Web瀏覽器] "undefined" [Web瀏覽器] "程序員"上面Person.prototype.career = "程序員";就是通過原型來添加的屬性,所有繼承這個Person的對象,都具有career這個屬性。
這個過程是這樣的,當輸出p.career的時候,首先會在對象p找,因為p對象沒有career這個屬性,這就是為什么會輸出undefined的原因,然后繼續(xù)向上查找,在Person.prototype中找到了career,然后就輸出了“程序員”。?
要了解原型的概念,應該知道_proto_、prototype以及constructor他們之間是什么聯(lián)系
那么就來分析一下var p = new Person(); 這個過程
上面這個分析圖可以很好的展示,三者的關系,
首先要知道幾個地方,
第一點:就是Empty()函數(shù),這個函數(shù)是所有函數(shù)的原型,并且他很特殊沒有prototype
第二點:__proto__是內(nèi)部原型,prototype是構造器原型(構造器其實就是函數(shù),所以上面才說這個是函數(shù)對象才有的,而_proto_是每個對象都有的。我的理解它才是構成原型鏈的原因)
①.從中間開始看,首先我創(chuàng)建了一個函數(shù)person(),同時JS幫我創(chuàng)建了一個原型對象person.prototype
并把我的person()的prototype指針指向了它,原型對象中有一個constructor屬性,指向了我的person()函數(shù)。
②.當我new一個person實例的時候,新創(chuàng)建的實例對象p的_proto_指向了person.prototype
這也是為什么,我在person.prototype中添加屬性,p也能反映出來的根本原因。
③.person.prototype也是一個對象,那么他的_proto_是誰呢,如上圖就是Object.prototype,這也不難理解,因為Object是Javascript中所有對象的父級對象,我們創(chuàng)建的所有對象都繼承于此,包括內(nèi)建對象。同樣因為它也是對象,那么它也擁有_proto_,圖上表示了它的原型就是null
我們可以打印每一屬性的值來進行確認:
//Person函數(shù)的原型對象 console.log(Person.prototype); //Person原型對象的Constructor console.log(Person.prototype.constructor); //判斷實例對象p的原型,是不是Person.prototype console.log(p.__proto__ === Person.prototype?true:false); //函數(shù)對象Person的_proto_,是不是Empty() console.log(Person.__proto__); //Empty()是不是沒有prototype console.log(Person.__proto__.prototype); //Empty()的__proto__是不是Object.prototype console.log(Person.__proto__.__proto__ === Object.prototype?true:false); //Person.prototype的_proto_是不是Object.prototype console.log(Person.prototype.__proto__ === Object.prototype?true:false); //Object.prototype的_proto_是不是null console.log(Object.prototype.__proto__);輸出結果: [Web瀏覽器] "[object Object]" [Web瀏覽器] "function Person(){this.name="大橙子";this.age = 26;this.sex = "純爺們"; }" [Web瀏覽器] "true" [Web瀏覽器] "function Empty() {}" [Web瀏覽器] "undefined" [Web瀏覽器] "true" [Web瀏覽器] "true" [Web瀏覽器] "null"?
2.原型鏈
上面的原型我們舉的例子沒有特別明顯的顯示這個鏈的過程,看不到具體的繼承關系,所以再分析一個例子
Object.prototype.dead = true;function animal(){} animal.prototype.eat=true; animal.prototype.sleep=true;function bird(){this.fly = true; }bird.prototype = new animal(); var a = new animal(); var b = new bird();console.log(a.fly); console.log(a.eat); console.log(a.sleep); console.log(a.dead); console.log(b.fly); console.log(b.eat); console.log(b.sleep); console.log(b.dead);測試輸出: [Web瀏覽器] "undefined" [Web瀏覽器] "true" [Web瀏覽器] "true" [Web瀏覽器] "true" [Web瀏覽器] "true" [Web瀏覽器] "true" [Web瀏覽器] "true" [Web瀏覽器] "true"下面我再畫圖分析一下這個
①下圖是在bird.prototype = new animal();之前,創(chuàng)建好函數(shù)之后的狀態(tài)
?
②繼續(xù)執(zhí)行程序
從上圖就可以明顯看到
實例對象b->bird.prototype->animal.prototype->Object.prototype->null有一個鏈式的繼承關系
也就是為什么
console.log(b.eat);
console.log(b.sleep);
console.log(b.dead);
會打印出來true的原因了。
?
轉載于:https://www.cnblogs.com/dcz2015/p/5391971.html
總結
以上是生活随笔為你收集整理的Javascript原型钩沉的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 因kuaipan等PPA造成的Dupli
- 下一篇: 高效 Java Web 开发框架 Jes