【追尋javascript高手之路04】理解prototype


前言

中午時候我去葯店稱了下體重,好家伙!我減肥成功了,足足比上個月瘦了10斤!於是想減肥就去鄭州吧。。。

然后回來迷迷糊糊睡了一會,居然想起了周三的面試,有點小遺憾有點小觸動。

這次回成都后,還沒有正式找工作,我也在審視自己,想起了上次二面時候面試官問的一個問題:

你有神馬值得自豪的事情嗎?你有什么能證明自己性格特點的事情嗎?

這個其實想讓我自我吹噓一番嘛,但是我出來工作后是有幾件出彩的事情,但是感覺在他面前就說不來也不算事了,於是弱弱的說了一下自己堅持寫了3個月的博客了。

但是在他看來,3個月似乎不算事。。。其實想一想3個月確實不算什么,轉瞬即逝。我還有很多不懂的東西,各個方面。

所以下周我還是應該找一個工作安定下來,認認真真做一兩個產品,然后堅持把今年的博客寫完先!希望下次被人問到這個問題時候我可以自豪的說,我每天都堅持學習了2,3個小時,並且分享出來了博客,並且以此為樂。

PS:其實我在睡覺時候,主要想到的是,怎么我的機票還沒給我報銷。。。賬上沒錢啊。。。:)

好了,廢話結束,進入我們下午的學習吧,我們這次又來看看我們的prototype吧,面向對象我又來了,因為這個東西前面我們就寫過代碼,這里直接上重點。

原型鏈

我們創建的每一個函數都包含一個prototype(原型)屬性。
他是一個指針,指向一個對象,這個對象是包含可以由特定類型的所有實例共享的屬性和方法。
通俗點:prototype就是一模板,新創建的模板就是對他的一個拷貝

每個prototype對象又會包含一個constructor屬性,該屬性意義不大,而且經常被覆蓋,但是他是指向構造函數的,我們在類型判斷的地方也許用得到。

創建新實例后,實例內部包含一個[[Prototype]]的內部屬性(指針,__proto__),指向構造函數的prototype,這個關系是你搞不掉的,我們這里有幾個方法需要各位記住:

我們通過isPrototypeOf來確定某個對象是不是我的原型
hasOwnPrototype 可以檢測一個屬性是存在實例中還是原型中
意思是該屬性不能是原型屬性才返回true

說了這么多,我們來上個圖吧:

1 var Person = function (name, age) {
2     this.name = name;
3     this.age = age;
4 };
5 Person.prototype.getName = function () {
6     return this.name;
7 };
8 var y = new Person('葉小釵', 30);

我們一般是這樣干的,但是name與age在外邊是可以訪問的喲。

1 var s1 = Person.prototype.isPrototypeOf(y); //true;
2 var s2 = y.hasOwnProperty('name'); //true
3 var s3 = y.hasOwnProperty('id'); //false
4 var s4 = y.hasOwnProperty('getName');//false

繼承時原型鏈的關系

我們這里直接上圖了,因為我們的Person函數繼承自Object構造函數,說白了就是Person的prototype是object構造函數的一個實例:

由於之前寫過類似的文章,這里就不多說了。

做兩道題吧

第一題

1 var proto = { a: 1 };
2 function cls() { };
3 var obj1 = new cls();
4 cls.prototype = proto;
5 //obj1.a現在是什么?

這里cls是作為構造函數使用的,obj1實例化后其內部屬性[[Prototype]]指向cls的原型對象(這里相當於一個復制),后面改變了構造函數的原型指向

這道題其實在勾引我們,我們很有可能就會回答說1,其實答案是undefined。因為構造函數cls創建后,其原型對象已經形成,最后只是切斷了cls和其原型的聯系,

obj1的__proto__([[Prototype]])依舊指向原來的那個原型,而不是proto。

第二題

1 function cls() { };
2 var obj1 = new cls();
3 cls.prototype.a = 1;
4 //obj1.a現在是什么?
5 alert(obj1.a);

這道題與上題有所不同,雖然事后更改了原型,但是都是更改的堆上的同一對象,所以答案是1

第三題

我找到了一個閉包的題目,順便拿出來吧

1 function build() {
2     var i;
3     return function () { alert(i++); }
4 }
5 var f1 = build();
6 var f2 = build();
7 var s1 = f1 == f2;
8 var s = '';
9 //請說明:f1和f2是否是同一函數,分別調用f1() f2()會產生什么效果。

這道題有點意思哦,為了讓其運行正常,我們給i一個1吧。

若是這里將函數返回值去掉的話,f1與f2就是一樣的了,但是由於里面產生了閉包,所以f1與f2各自維護着自己的環境與閉包。

我們來理一理這道題:

5行執行時候會創建一個執行環境,以及相關作用域鏈,然后初始化arguments以及this,最后與i、以及匿名函數一起初始化形成了活動對象(有問題請提出

5行結束后,執行環境以及作用域鏈被回收,但是活動對象被留了下來。

在第六行f2初始化時,又重新執行了一次這個過程。

所以其最后調用時候所使用的活動對象不一致,所以兩個函數不是一個函數啦。

錯誤:我剛剛吃飯時候想了下,這里的活動對象應該不包括this

PS:我暫時找不到好的題目了,若您有好的題目,請留下

結語

今天做了一次回顧,下面點再學習其它知識吧,現在先去吃個飯吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM