js原型鏈
說實話js這門語言之前沒有仔細研究過,如今研究起來感受好麻煩,對於原型鏈這個說法我也是剛接觸不久,就試着說說個人理解吧!
關於上一篇咱們說了js整個函數體系結構,想了解的能夠點擊這裏,這裏隨便找到一些對原型的小測試,你能夠看看會不會,其中Person是一個構造函數,person1是構造函數的一個實例;
person1.__proto__ 是什麼?//person1.__proto__ == Person.prototype
Person.__proto__ 是什麼?//Person.__proto__ == Function.prototype
Person.prototype.__proto__ 是什麼?//Person.prototype.__proto__ == Object.prototype
Object.__proto__ 是什麼?//Object.__proto__ == Function.prototype
Object.prototype__proto__ 是什麼?//Object.prototype__proto__ == null
知道了這些就差很少了,咱們繼續看;
1.特殊的Math和JSON
這兩個內置對象有點不一樣,上次尚未注意看,由於其餘的內置對象都是Function的實例,好比Date,Number等,舉個例子:
Date instanceof Function //true
Date.constructor == Function //true
Date.__proto__ == Function.prototype //true
可是當咱們用Math對象和JSON對象測試的時候確實false,其實能夠把Math和JSON對象看做Object的實例:
//Math和JSON同樣,這裏以Math爲例
Math instanceof Object //true
Math.constructor == Object //true
Math.__proto__ == Object.prototype //true
這兩個對象比較特殊,注意一下和其餘的內置對象必定要分開!!!
2.繼承
繼承能夠說是每個面嚮對象語言確定有的,由於符合咱們現實的想法,子承父業嘛!若是你爸比較有錢,你繼承了幾個億的家產確定一輩子無憂;若是你爸是個普通人,那即便繼承了家產也沒有多少啊!仍是要靠本身奮鬥。
在js中的繼承也一個樣,若是一個構造函數設計得很好,那麼兒子等後代就會很舒服啊!繼承的話,從Object開始,下圖所示,你看Object中你以爲哪一個部分最重要,應該被繼承下去,固然是原型啊!因此說繼承就是指的是原型中的全部東西都會被繼承到後代中。。。。
咱們能夠驗證一下:
複製代碼
Object.prototype.say = function(){alert("你好!")};
var obj = new Object();
obj.say();//頁面會有彈窗「你好!「,說明在obj實例中調用的say方法其實就是調用的是Object中原型中的say方法
//還能夠用另一個方式,就是用Math或者JSON對象也會有一樣的效果
Object.prototype.say = function(www.chaoyuepint.com){alert("你好!")};
Math.say();
複製代碼
這個可能有點晦澀難懂,沒關係咱們繼續往下看!看了他們的調用機制就懂了;
3.js方法調用機制
簡單測試一下,我就是分別在Object原型內外,構造函數Person原型內外,以及per實例中寫了一些方法,可能不少人看着都頭暈了。。。
複製代碼
Object.say = function(){alert("object----say")}
Object.listen = function(){alert("object----listen")}
Object.prototype.say = function(){alert("Object.prototype---say")};
Object.prototype.listen = function(){alert("Object.prototype---listen")};
var Person = new Function();
Person.say = function(){alert("Person>>>>>>say")};
Person.run = function(){alert("Person>>>>>>run")};
Person.listen = function(){alert("Person>>>>>>listen")};
Person.prototype.say = function(){alert("Person.prototype>>>>>>say")};
Person.prototype.run = function(){alert("Person.prototype>>>>>>run")};
var per = new Person();
per.say = function(){alert("per+++++++say"www.seocelve.com)};
per.say(); //per+++++++say
per.listen(www.oushenggw.com); www.xcdeyiju.com //Object.prototype---listen
per.run(); //Person.prototype>>>>>>run
複製代碼
上面的太繁瑣,沒耐心看就算了,我就說說我得出的結論:原型外面的函數(也能夠叫作方法)不會被繼承,也就是說只要是在原型外面的函數只能本身用,不能給後代用;而對於原型裏面的函數,對於後代來講是可見的,
注意:圖中我爲了看起來簡潔,省略了一點東西,就是那麼__proto__屬性,爲何實例可以找到它爸爸構造函數的原型呢?就是經過這個屬性,而構造函數中也有一個__proto__屬性,指向Object的原型,經過這個原型的話,咱們的實例就可以慢慢往上找原型,一直能夠找到Object的原型,這就是所謂的原型鏈。。。。
因此根據這個特性,js一開始就在Object的原型中放置了一些經常使用的函數,因此自定義構造函數的實例一開始就能夠調用一些方法,這些方法不是咱們定義的,而是官方幫你先放到Object的原型中的,固然你也能夠在實例或構造函數中弄個一樣名字的函數,將官方那個給覆蓋掉。。。。。
4.js中方法類型
我js中的方法大概分爲三種(對於js這樣的語言來講,沒有類的概念好不爽,咱們就把構造函數看做類吧。。。。):類方法,實例方法,原型方法
那麼這三種方法究竟是幹嗎的呢?我就隨便舉個例子:
複製代碼
var Person = function(name){
this.name = name;
this.say = function(){alert("say.....")};//實例方法
}
Person.say = function(){alert("Person say.....")}//類方法,只能經過構造函數名來調用
Person.prototype.say=function(){alert("prototype say.....")}//原型方法
var per = new Person();
per.say();//調用實例方法,注意當實例方法和原型方法同名的時候優先調用實例方法,若是實例方法沒有say方法,那就會調用原型中的say方法
Person.say();//調用類方法
Person.prototype.say();//調用原型方法
複製代碼
5總結
怎麼說呢?感受js結構太糟糕了,看了很久才知道一個大概的輪廓,還有不少的東西沒看到,好比咱們知道原型實際上是一個當前構造函數的實例,那麼咱們可不能夠把其餘對象的實例賦值過來呢?好比Student.prototype = new Person(),這樣行嗎?固然能夠,這樣的話可讓Student的實例訪問Person的原型的方法,實現了繼承。。。。
哎,有機會再來啃js吧,還有好多東西要看。。。。因爲看js沒多久,有什麼說得有誤的地方歡迎指出!
--------------以上皆原創,給將來的本身留下一點學習的痕跡!--------
標籤: js函數