不少job 的描述都說要求精通 javascript 面向對象編程,可是根據通常的套路,寫精通其實就是熟練,寫熟練其實就是通常,寫通常其實就是懵逼!javascript
雖然話說如此,可是咱們仍是要熟練使用 javascript 面向對象編程的,畢竟這是js社會高能人才的其中一個標準,這裏我就用一個鮮活的例子來講明和理解咱們應該如何使用javascript 面向對象的方式來編程。java
剛開始最初,咱們建立對象的方式是這樣的:編程
// 。。。。每次都要寫上面的一大段代碼,只是爲了建立一個 food var food = new Object(); food.name = "蘋果"; food.sayName = function() { console.log("我是" + this.name); };
可是這樣建立起來很麻煩,寫的代碼也是很長,若是要建立好多對象,例如我製造了10000個食物,就要寫10000次這一大段代碼了,因此後來聰明的工程師改成了這樣寫:函數
// 起碼比以前的少了幾行,也整潔了一些 var food = { name: "蘋果", sayName: function() { console.log("我是" + this.name); } };
起碼代碼少了一些,可是仍是沒辦法很好解決我要寫100000段代碼的問題,因此再後來的人們就開始使用一些高級玩意來解決這個問題。性能
經過抽象出建立具體對象的過程,用函數來進行封裝,換句話來講,就是抽象了一個 food 的工廠,而後經過對這個工廠傳入不一樣的材料,來生成不一樣的食物。學習
function createFood(name) { var o = new Object(); o.name = name; o.sayName = function() { console.log("我是" + this.name); }; return o; } var food1 = createFood("蘋果"); var food2 = createFood("蘋果");
這裏能夠看到food1,food2 就是這樣被製造出來的,而後只須要少許的代碼(預先定義好一個生產工廠函數),就能夠完成大量的事情,完全解決了問題,實現了多快好爽的新局面。可是用了一段時間以後,隨之而來發現一個新問題,當食物多起來的時候,老闆貌似不知道哪些食物是屬於那些分類的(假設老闆是 zz),那怎麼辦呢?網站
// 都統一返回是[Function: Object],沒辦法用區分識別(賣個關子,你不用管那個constructor) console.log(food1.constructor) // 返回[Function: Object] console.log(food2.constructor) // 返回[Function: Object]
通過一番智慧交流以後,聰明的人們想出了一個方法,使用一個在對象裏面的 constructor
函數來識別那些不同的對象,相似使用部門工牌來標記這我的是是屬於哪一個部門的。this
function Food(name) { this.name = name; this.sayName = function() { console.log("我是" + this.name); }; } var food1 = new Food("蘋果"); var food2 = new Food("蘋果"); // 假設這裏有一個其餘的食物,多是冒充的 var food3 = new otherFood("蘋果");
由於要實現相似工牌的方式來識別,因此在建立food的工廠裏作一些調整:spa
var o = new Object();
this
對象return
語句Food
`對象作了以上的改變以後,整個建立對象的模式被改變了:設計
Food
的構造函數(其實就是以前的工廠函數createFood,可是如今升級了)new
來建立一個對象(如今的 Food 用 new 來先建立)this
指向這個新對象(將升級版的工廠送給這個用 new
建立的 food)return
,自動返回新對象(升級版的工廠會自動返回構造好的 food 對象)經過這種方式,咱們製造出來的食物都會有一個 constructor
爲 Food 的標記來標識,若是看到不是的話,那確定就不是咱們製造的。
console.log(food1.constructor) // 返回[Function: Food] console.log(food2.constructor) // 返回[Function: Food] console.log(food3.constructor) // 返回[Function: OtherFood] // 檢驗的方式有兩種 console.log(food1.constructor == Food) // 返回 true console.log(food2.constructor == Food) // 返回 true console.log(food3.constructor == Food) // 返回 false ,這個不是咱們製造的食物 console.log(food1 instanceof Food) // 返回 true console.log(food3 instanceof Food) // 返回 false,這個不是咱們製造的食物
能夠看到,使用了新技術(constructor
模式技術)以後,在沒有增長工做量的狀況下,解決了使人頭痛的問題,簡直是完美,不過過了一段時間以後,發現好像仍是有些瑕疵,使用構造函數constructor
模式的時候,函數裏面的每一個方法都會在每一個實例上從新建立一遍,那麼最明顯的地方是:
console.log(food1.sayName == food2.sayName); // 返回 false
由於使用new
來建立實例,new
的話還會把構造函數裏面的方法也一塊兒建立,由於方法也是函數,而函數的實例化也會被new
觸發:
// 省略了其餘部分,只關注方法部分 this.sayName = function() { console.log("我是" + this.name); }; this.sayName = new function() { console.log("我是" + this.name); }();
這樣就會形成內存和時間和性能的浪費,明明不須要從新重建新的函數實例的。
其實在以前的工廠模式裏面,也存在這個問題,不過工廠模式更完全,直接徹底建立一個新對象,而構造函數模式的話只是方法會被從新建立。
那怎麼解決呢?會用到原型模式,下回分解。
做者: 慫如鼠
網站: https://www.whynotbetter.com 本做品著做權歸做者全部,商業轉載請聯繫做者得到受權,非商業轉載請註明出處。