‘工欲善其事,必先利其器’,在深刻學習JavaScript以前,我認爲咱們頗有必要了解如下,JavaScript這門面向對象的動態語言究竟是一門什麼樣的語言。git
動態類型語言對變量類型的寬容,給實際編碼帶來了很大的靈活性。因爲無需進行類型的 檢測,咱們能夠嘗試調用任何對象的任何方法,而無需考慮它本來是否被設計爲擁有該方法。github
說到這裏,咱們就不得不提一下鴨子類型了。鴨子類型就說偶們只關注對象的行爲,而不關注對象自己。編程
咱們知道JavaScript是面向接口編程的語言,而非是面向實現編程的。所以只要咱們給對象添加pop,push方法,增添length屬性,那麼這個對象就能夠當數組使用。設計模式
雖然,JavaScript也是面向疾苦的語言,可是,它和靜態類型語言的面向接口編程不一而足。數組
它將可變的部分與不可變的部分分離開來,吧可變的部分封裝起來(對象擁有相同的類型,都有相同的方法,接受相同的調用,卻返回不一樣的結果)瀏覽器
下面是一個對象的多態:函數
var robotA = { dance: function() { console.log('robtA') } }; var robotB = { dance: function() { console.log('robtB') } } var robotAction = function(robot) { if(robot.dance instanceof Function) robot.dance() } robotAction(robotA); // robtA robotAction(robotB); // robtB
在JavaScript中函數被看成第一等對象,也便是說函數自己也是對象,咱們知道由於js是動態類型語言,因此函數不只能夠用來封裝行爲,而且能夠被看成參數四處傳遞。當咱們對函數發起調用時,函數會返回不一樣的結果,這是多態的一種體現,也是不少設計模式能被高階函數代替實現的緣由。學習
封裝的目的是將信息隱藏。編碼
封裝包括數據的封裝,實現的封裝和 變化的封裝。prototype
1.數據的封裝
在js中咱們只能依賴變量的做用域來進行封裝。能夠實現全局做用域和局部做用域,在ES6以前咱們使用函數來建立做用域,但在以後咱們也可用let來建立做用域。
2.實現的封裝
實現的封裝使得對象的內部變化對其餘對象來講是不可見的。對象對他本身的行爲負責,其餘對象不關心它的內部實現。
封裝使得對象間的耦合變得鬆散,對象間只能經過暴露的API接口進行通訊,只要咱們不修改對象的對外接口,怎麼樣修改對象都不會影響其餘對象的功能。
3.變化的封裝
它就是將應用中穩定的部分和變化的部分隔離開來。若是咱們將變化的部分封裝起來,那麼在應用的開發中咱們將很容易的實現替換。這樣能夠最大程度的保證應用的穩定性和可擴展性。
前面咱們已經說過JavaScript沒有類式繼承,取而代之的是原型的繼承,這是語言的開發者根本就沒打算在js中引入類這個概念,而是引入了原型的概念。
在原型的編程思想中對象是經過複製而來的,克隆而來的對象與原對象看不出什麼區別。
說到克隆對象,在ES5中有一個Object.create()方法來實現克隆,這個方法有兼容性問題,若是要在只支持ES3的瀏覽器中這就有一個問題。咱們通常用下面的代碼來解決:
Object.create = Object.create || function(obj) { var F = function() {}; F.prototype = obj; return new F() }
在js這種類型模糊的語言中,建立對象很容易,也不存在類型耦合的狀況。
js中的對象的實現是經過js的原型系統來實現的,前面也說過在js中一切皆對象,因此,要想很好的掌握js就要認真研究一下它的原型。
根據JavaScript的設計者本意,除了undefined以外的全部數據都是對像,咱們知道js中的對象都是經過原型克隆而來的的,而在js中對象爲Object,因此數據都是經過Object.prototype而來的(Object對象克隆自Function)。示例代碼以下:
var animal = { name: 'lzb' }; var person = function(){}; person.prototype = animal; var lzb = new person(); console.log( lzb.name ); // lzb
其實嚴格意義上來講實現對象的構造器有原型,若是對象的請求無響應,對象把它的請求委託給它的構造器的原型。
這個在網上說法不一,有的人認爲原型繼承很爛,而且說既然人們總結出了JavaScript的設計模式,而模式的出現自己就意味着語言的不足。可是,有的人認爲它在將來至關長的一段時間仍是有市場的,而且js自己就在自我矯正,用一些新的特性來代替設計模式,ES5中的Object.create()來代替原型模式克隆對象,而ES6中的class的引入也是這個緣由,雖然其背後的實現仍是原型來克隆對象,但它的出現的確解決了必定的問題。再加上如今開發人員對它的興趣大增,因此我認爲原型繼承有將來。
好了,今天的基礎回顧就到這裏,順便咱們瞭解瞭如下原型設計模式,原型模式的地位很重要,它和js的原型繼承一脈相承。
後續文章更新文章請關注https://github.com/lvzhenbang/article