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(){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")}; per.say(); //per+++++++say per.listen(); //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沒多久,有什么說得有誤的地方歡迎指出!


免責聲明!

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



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