天天看點

【追尋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:我暫時找不到好的題目了,若您有好的題目,請留下

結語

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

本文轉自葉小钗部落格園部落格,原文連結http://www.cnblogs.com/yexiaochai/p/3162389.html,如需轉載請自行聯系原作者

繼續閱讀