JS為什么會有原型的概念?
因為早期的瀏覽器只能用來瀏覽,不具備與訪問者互動的能力。比如,如果網頁上有一欄"用戶名"要求填寫,瀏覽器就無法判斷訪問者是否真的填寫了,只有讓服務器端判斷。
如果沒有填寫,服務器端就返回錯誤,要求用戶重新填寫,這太浪費時間和服務器資源了。
這個時候需要一門網頁腳本語言,這種腳本語言能夠完成一些簡單的操作,比如判斷用戶有沒有填寫表單。剛好這個時候是向對象編程(object-oriented programming)最興盛的時期,C++是當時最流行的語言,而Java語言也馬上推出。
所以Javascript作者也受到了啟發,Javascript里面所有的數據類型都是對象(object),這一點與Java非常相似。但是直接使用java的"繼承"機制來實現,又覺得過于笨重,但是,Javascript里面都是對象,必須有一種機制,將所有對象聯系起來。所以,javascript作者最后還是設計了"繼承"。
但是,他不打算引入"類"(class)的概念,因為一旦有了"類",Javascript就是一種完整的面向對象編程語言了,這好像有點太正式了,而且增加了初學者的入門難度。
他考慮到,C++和Java語言都使用new命令,生成實例。
C++的寫法是:
- ClassName *object = new ClassName(param);
Java的寫法是:
- Foo foo = new Foo();
這時,他想到C++和Java使用new命令時,都會調用"類"的構造函數(constructor)。他就做了一個簡化的設計,在Javascript語言中,new命令后面跟的不是類,而是構造函數。
但是很快發現用構造函數生成實例對象,有一個缺點,那就是無法共享屬性和方法。
每一個實例對象,都有自己的屬性和方法的副本。這不僅無法做到數據共享,也是極大的資源浪費。
最終加入了prototype屬性的引入
考慮到這一點,作者決定為構造函數設置一個prototype對象屬性。
所有實例對象需要共享的屬性和方法,都放在這個對象里面;那些不需要共享的屬性和方法,就放在構造函數里面。
實例對象一旦創建,將自動引用prototype對象的屬性和方法。
由于所有的實例對象共享同一個prototype對象,那么從外界看起來,prototype對象就好像是實例對象的原型,而實例對象則好像"繼承"了prototype對象一樣。
面試總結回答
- JavaScript采用原型編程,所有對象都能共享原型上的方法,節省內存;
- 同時基于原型這一實現思想,JavaScript通過找對原型鏈,方便地實現了繼承。
這就是原型編程帶來的2個最大好處!!!
參考資料
內容有最簡化,如果需要看原始總結請查看阮一峰博客↓
http://ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html
https://blog.csdn.net/daigualu/article/details/54772799
本文轉載自微信公眾號「前端人」,可以通過以下二維碼關注。轉載本文請聯系前端人公眾號。