理解JavaScript中原型繼承

來源:互聯網
上載者:User
1,解決上篇的問題先

前面一篇文章,我發了一堆的牢騷,想來也是很愚蠢的,只是被JavaScript搞的頭疼,不爽而已。像許多東西你不懂的時候以為他是屎,當你懂了時候才知道他是寶。

書也是讀第二遍的時候才能懂,08年能就讀了愛民的《JavaScript語言精髓與編程實踐》,而且也通讀了語言精髓的部分,而且還和他通郵件聊了一點。不過當前我也沒有讀懂,我在書上有所記錄。

現在看來Crockford的《JavaScript:Good Parts》中說的也對JavaScript確實有比較狗屎的地方,當然瑕不掩玉,JavaScript確定有著另人吃驚的能力。先來解決上篇的問題,我們再看看上篇的代碼:

function Shape(){  this.area = function(){};}  function Point(){  this.x = 0;  this.y = 0;}  var p = new Point; //為啥是undefine,因為instace沒有prototype屬性,prototype對於p來說只是一個普通地跟p.val一樣是一個undefined的屬性。console.log(p.prototype);     //為啥又是指向Point的function,因為p沒有constructor,只有Point.prototype有,通過原型尋找,即p.constructor == Point.prototype.constructor == Point;console.log(p.constructor);console.log(p.constructor == Point.prototype.constructor);  console.log(p.constructor == Point);  console.log("-----------------------------");  p.prototype = new Shape();console.log(p.area);          //為啥又是undefine,不是設定了原型對象嘛,我操。//var p = new Point;做了下面三步:p={}; p.__proto__=Point.prototype=new Object(); Point.apply(p);//也就是說p的原型已經確定是new Object(),即一個Null 物件。   Point.prototype = new Shape();  //設定原型console.log(p.area);          //TMD還是不行,我設定了類型的原型對象啊。p中沒有area屬性,p的原型new Object()中也沒有area屬性,當然就是undefined,無比的正確  Point.prototype.area = function(){};console.log(p.area);          //你媽,為什麼啊。同上,p的原型在定義時已經確定就他媽的是一個Null 物件  var p2 = new Point;console.log(p2.area);         //我操,這時又可以了@#¥%……&*(//var p2 = new Point;的工作過程:p2={},p2.__proto__=Point.prototype=new Shape();Ponit.apply(p2);//關鍵是第27行我們已經設定了Point.prototype這個原型為new Shape(); Point.prototype.val = 10;console.log(p2.val);         //這下好理解了,p2中未定義val,這時去原型Point.prototype中找,找到了為10.Shape.prototype.val2 = 20;console.log(p2.val2);       //p2中沒有val2,去Point.prototype(即new Shape())中找,new Shape()的__proto__為Shape.prototype,終於找到了。
2,一些JavaScript的總結

先謝謝部落格園的湯姆的一張圖:

 

2.1 JavaScript中函數也是對象

如果感覺這不好理解,看下面的代碼

//函數第一種寫法,更能看出函數也是objvar f1 = function Point(){    this.x = 0;    this.y = 0;}//函數第二種寫法,與上面等效function f1(){    this.x = 0;    this.y = 0;}

除此之外,函數的原型是f1.__proto__ == Function.prototype; Function.__proto__ == Object.prototype; Object.__proto__ = null;

 

2.2 利用new 建構函式()來建立對象做了些什麼

比如 var p = new Point();這句話做下以下工作:

var p = {};

p.__proto__ == Point.prototype;    //很關鍵的一步,原型繼承來自於這裡

Point.apply(p);

剛才看Crockford的視頻,看到了new的JavaScript實現:

function new(func,arguments){    var that = Object.create(func.prototype);   //建立一個對象,並將期__proto__設定為func.prototype指向的object instance.    result = func.apply(that, arguments);    return (typeof result === 'object' && result) ||  that;}

 

2.3 一些注意點

a,只有構造器有prototype屬性,即Point.prototype。prototype是(指向)一個執行個體(instance)

b,執行個體中有__proto__屬性,即p.__proto__;原型回溯時就通過些屬性。

c,p.prototype只是p的一個普通屬性。系統沒有對此有約定和特殊照顧。

d,構造器.prototype.constructor指向構造器自身,即Point.prototype.constructor == Point;

e, p.constructor == Point.prototype.constructor == Point;

 

2.4原型鏈的維護

如果你不想通過公開屬性比如constructor來回溯整個原型鏈,你不用考慮太多。

但若你想回溯,就必須留心了。比如

function MyObject(){};function MyObjectEx(){};MyObjectEx.prototype = new MyObject(); //這句話會使得下面成立var o = new MyObjectEx();console.log(o.constructor == MyObject);   //我們在建立原型鏈時,將constructor指向打亂了。//解法1MyObjectEx.prototype = new MyObject();MyObjectEx.prototype.constructor = MyObjectEx;  //手動修改constructor指向//上面解法的問題是MyObject.prototype.constructor其實應該指向MyObject這樣才能完成原型回溯,這便有瞭解法2//解法2function MyObjectEx(){    this.constructor = arguments.callee;   //Or, this.constructor = MyObjectEx;}MyObjectEx.prototype = new MyObejct();//這樣MyObjectEx.Instance.constructor == MyObjectEx//並且MyObjectEx.prototype.constructor = MyObject

 

2.5 學JavaScript不能太糾結於實現的細節

你可以糾結與語言的細節,但不要糾結於實現的細節(SpideMonkey,JScript)。有些問題就是很奇怪。

比如:

var b = {};

console.log(b.__proto__ instanceof Object)  //此處是false即使我用debugger看到他是Object

 

如果你還想看一些詭異的地方,移步至《Wat》

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.