摘要:我們通過表單驗證的功能,來逐步演進面向對象的方式對于剛剛接觸的朋友來說,如果要寫一個驗證用戶名,密碼,郵箱的功能,一般可能會這么寫表單驗證全局全局全局這種寫法,從功能上來說沒有什么問題,但是在團隊協作的時候,會造成覆蓋全局變量的問題,那要大
我們通過表單驗證的功能,來逐步演進面向對象的方式. 對于剛剛接觸javascript的朋友來說,如果要寫一個驗證用戶名,密碼,郵箱的功能, 一般可能會這么寫:
1 //表單驗證 2 var checkUserName = function(){ 3 console.log( "全局checkUserName" ); 4 }; 5 var checkUserEmail = function(){ 6 console.log( "全局checkUserEmail" ); 7 }; 8 var checkUserPwd = function(){ 9 console.log( "全局checkUserPwd" ); 10 };
這種寫法,從功能上來說 沒有什么問題, 但是在團隊協作的時候, 會造成覆蓋全局變量的問題, 那要大大降低覆蓋的可能性, 一般會在外面套一個對象
1 var Utils = { 2 checkUserName : function(){ 3 console.log( "Utils->checkUserName" ); 4 }, 5 checkUserEmail : function(){ 6 console.log( "Utils->checkUserEmail" ); 7 }, 8 checkUserPwd : function(){ 9 console.log( "Utils->checkUserPwd" ); 10 } 11 } 12 13 checkUserEmail(); 14 Utils.checkUserEmail();
上面這種方式,是字面量方式添加,在設計模式里面,也稱為單例(單體)模式, 與之類似的可以通過在函數本身添加屬性和方法,變成靜態屬性和方法,達到類似的效果:
1 var Utils = function(){ 2 3 } 4 Utils.checkUserName = function(){ 5 console.log( "Utils.checkUserName" ); 6 } 7 Utils.checkUserPwd = function(){ 8 console.log( "Utils.checkUserPwd" ); 9 } 10 Utils.checkUserEmail = function(){ 11 console.log( "Utils.checkUserEmail" ); 12 } 13 14 Utils.checkUserEmail(); 15 16 for( var key in Utils ){ 17 ( Utils.hasOwnProperty( key ) ) ? console.log( key ) : ""; 18 } 19 20 //加在函數上面的屬性和方法,無法通過對象使用 21 var oUtil = new Utils(); 22 oUtil.checkUserEmail();//錯誤
還可以通過函數調用方式,返回一個對象,把方法和屬性寫在對象中, 這種方式 跟面向對象沒有什么關系,只是從函數的返回值角度來改造
1 //使用函數的方式 返回一個對象 2 var Util = function(){ 3 return { 4 checkUserName : function(){ 5 console.log( "userName..." ); 6 }, 7 checkUserPwd : function(){ 8 console.log( "userPwd..." ); 9 }, 10 checkUserEmail : function(){ 11 console.log( "userEmail..." ); 12 } 13 } 14 } 15 Util().checkUserEmail();
還可以通過類似傳統面向對象語言,使用構造函數方式 為每個實例添加方法和屬性, 這種方式,存在一個問題, 不能達到函數共用,每個實例都會復制到方法.
1 var Util = function(){ 2 this.checkUserName = function(){ 3 console.log("userName"); 4 }; 5 this.checkUserEmail = function(){ 6 console.log("userEmail"); 7 }; 8 this.checkUserPwd = function(){ 9 console.log("userPwd"); 10 }; 11 } 12 13 var oUtil1 = new Util(); 14 var oUtil2 = new Util(); 15 console.log( oUtil1.checkUserEmail === oUtil2.checkUserEmail );//false 一般,我們可以通過原型屬性(prototype)改造這種方式,達到不同實例共用同一個方法 1 var Util = function(){ 2 3 }; 4 Util.prototype.checkUserName = function(){ 5 console.log("userName"); 6 }; 7 Util.prototype.checkUserPwd = function(){ 8 console.log("userPwd"); 9 }; 10 Util.prototype.checkUserEmail = function(){ 11 console.log("userEmail"); 12 }; 13 var oUtil1 = new Util(); 14 var oUtil2 = new Util(); 15 console.log( oUtil1.checkUserEmail === oUtil2.checkUserEmail );//true
也可以把原型對象上的所有方法,使用字面量方式簡寫
1 var Util = function(){ 2 3 }; 4 Util.prototype = { 5 checkUserEmail : function(){ 6 console.log( "userEmail" ); 7 }, 8 checkUserName : function(){ 9 console.log( "userName" ); 10 }, 11 checkUserPwd : function(){ 12 console.log( "userPwd" ); 13 } 14 }; 15 var oUtil1 = new Util(); 16 var oUtil2 = new Util(); 17 console.log( oUtil1.checkUserEmail === oUtil2.checkUserEmail );//true
注意: 字面量方式和原型對象一個個添加 這兩種不要混用, 否則會產生覆蓋
如果我們想把面向對象的使用方式更加的優雅,比如鏈式調用, 我們應該在每個方法中返回對象本身,才能繼續調用方法, 即返回this
1 var Util = function(){ 2 return { 3 checkUserName : function(){ 4 console.log( "userName..." ); 5 return this; 6 }, 7 checkUserPwd : function(){ 8 console.log( "userPwd..." ); 9 return this; 10 }, 11 checkUserEmail : function(){ 12 console.log( "userEmail..." ); 13 return this; 14 } 15 } 16 } 17 // 方法中如果沒有返回this,下面這種調用方式是錯誤的 18 Util().checkUserEmail().checkUserName(); 19 20 // 方法中返回對象本身,可以鏈式調用 21 Util().checkUserEmail().checkUserName().checkUserPwd(); 1 var Util = function(){ 2 this.checkUserName = function(){ 3 console.log("userName"); 4 return this; 5 }; 6 this.checkUserEmail = function(){ 7 console.log("userEmail"); 8 return this; 9 }; 10 this.checkUserPwd = function(){ 11 console.log("userPwd"); 12 return this; 13 }; 14 } 15 16 new Util().checkUserEmail().checkUserName().checkUserPwd(); var Util = function(){ }; Util.prototype = { checkUserEmail : function(){ console.log( "userEmail" ); return this; }, checkUserName : function(){ console.log( "userName" ); return this; }, checkUserPwd : function(){ console.log( "userPwd" ); return this; } }; new Util().checkUserEmail().checkUserName().checkUserPwd(); 1 var Util = function(){ 2 3 }; 4 Util.prototype.checkUserName = function(){ 5 console.log("userName"); 6 return this; 7 }; 8 Util.prototype.checkUserPwd = function(){ 9 console.log("userPwd"); 10 return this; 11 }; 12 Util.prototype.checkUserEmail = function(){ 13 console.log("userEmail"); 14 return this; 15 }; 16 17 new Util().checkUserEmail().checkUserName().checkUserPwd(); 在實際開發中,我們經常需要擴展一些功能和模塊。擴展可以在本對象或者父類對象或者原型上 1 Function.prototype.checkUserName = function(){ 2 console.log("ghostwu"); 3 }; 4 5 var fn1 = function(){}; 6 var fn2 = function(){}; 7 8 console.log( "checkUserName" in fn1 ); //true 9 console.log( "checkUserName" in fn2 ); //true 10 11 fn1.checkUserName(); //ghostwu 12 fn2.checkUserName(); //ghostwu 如果我們使用上面這種方式擴展,從功能上來說,是沒有問題的,但是確造成了全局污染:通俗點說,并不是說有的函數都需要checkUserName這個方法,而我們這樣寫,所有的函數在創建過程中都會從父類的原型鏈上繼承checkUserName, 但是這個方法,我們根本不用, 所以浪費性能, 為了解決這個問題,我們應該要在需要使用這個方法的函數上添加,不是所有的都添加,另外關于in的用法,如果不熟悉,可以看下我的這篇文章:立即表達式的多種寫法與注意點以及in操作符的作用 1 Function.prototype.addMethod = function( name, fn ){ 2 this[name] = fn; 3 } 4 5 var fn1 = function(){}; 6 var fn2 = function(){}; 7 8 fn1.addMethod( "checkUserName", function(){console.log("ghostwu");}); 9 10 fn1.checkUserName(); //ghostwu 11 fn2.checkUserName(); //報錯
通過上述的改造,成功解決了全局污染, fn2這個函數上面沒有添加checkUserName這個方法,只在fn1上面添加
我們繼續把上面的方式,改成鏈式調用: 這里需要改兩個地方, 一種是添加方法addMethod可以鏈式添加, 一種是添加完了之后,可以鏈式調用
1 Function.prototype.addMethod = function( name, fn ){ 2 this[name] = fn; 3 return this; 4 }; 5 6 var fn1 = function(){}; 7 8 fn1.addMethod( "checkUserName", function(){ 9 console.log( "userName:ghostwu" ); 10 return this; 11 } ).addMethod( "checkUserEmail", function(){ 12 console.log( "userEmail" ); 13 return this; 14 } ).addMethod( "checkUserPwd", function(){ 15 console.log( "userUserPwd" ); 16 return this; 17 } ); 18 fn1.checkUserName().checkUserEmail().checkUserPwd(); 上面是屬于函數式 鏈式 調用, 我們可以改造addMethod方法, 在原型上添加函數,而不是實例上, 這樣我們就可以達到類式的鏈式調用 1 Function.prototype.addMethod = function( name, fn ){ 2 this.prototype[name] = fn; 3 return this; 4 }; 5 6 var fn1 = function(){}; 7 8 fn1.addMethod( "checkUserName", function(){ 9 console.log( "userName:ghostwu" ); 10 return this; 11 } ).addMethod( "checkUserEmail", function(){ 12 console.log( "userEmail" ); 13 return this; 14 } ).addMethod( "checkUserPwd", function(){ 15 console.log( "userUserPwd" ); 16 return this; 17 } ); 18 new fn1().checkUserName().checkUserEmail().checkUserPwd();
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87356.html
摘要:不必在構造函數中定義對象實例的信息。其次,按照一切事物皆對象的這餓極本的面向對象的法則來說,類本身并不是一個對象,然而原型方式的構造函數和原型本身也是個對象。第二個問題就是在創建子類型的實例時,不能向超類型的構造函數中傳遞參數。 前言 對象(Object)應該算是js中最為重要的部分,也是js中非常難懂晦澀的一部分。更是面試以及框架設計中各出沒。寫這篇文章,主要參考與JavaScrip...
摘要:在創建子類實例時,不能向超類型的構造函數中傳遞參數。構造函數繼承子類傳進的值是基本思想是在子類構造函數的內部調用超類或父類型構造函數。繼承保證構造函數指針指向如果想同時繼承多個,還可使用添加屬性的方式類繼承, OOP:Object Oriented Programming 面向對象編程。 題外話:面向對象的范圍實在太大,先把這些大的東西理解理解。 1.什么是對象? 根據高程和權威指南上...
摘要:在他的重學前端課程中提到到現在為止,前端工程師已經成為研發體系中的重要崗位之一。大部分前端工程師的知識,其實都是來自于實踐和工作中零散的學習。一基礎前端工程師吃飯的家伙,深度廣度一樣都不能差。 開篇 前端開發是一個非常特殊的行業,它的歷史實際上不是很長,但是知識之繁雜,技術迭代速度之快是其他技術所不能比擬的。 winter在他的《重學前端》課程中提到: 到現在為止,前端工程師已經成為研...
摘要:在他的重學前端課程中提到到現在為止,前端工程師已經成為研發體系中的重要崗位之一。大部分前端工程師的知識,其實都是來自于實踐和工作中零散的學習。一基礎前端工程師吃飯的家伙,深度廣度一樣都不能差。開篇 前端開發是一個非常特殊的行業,它的歷史實際上不是很長,但是知識之繁雜,技術迭代速度之快是其他技術所不能比擬的。 winter在他的《重學前端》課程中提到: 到現在為止,前端工程師已經成為研發體系...
摘要:避免脆弱的基類問題。紅牌警告沒有提到上述任何問題。單向數據流意味著模型是單一的事實來源。單向數據流是確定性的,而雙向綁定可能導致更難以遵循和理解的副作用。原文地址 1. 你能說出兩種對 JavaScript 應用開發者而言的編程范式嗎? 希望聽到: 2. 什么是函數編程? 希望聽到: 3. 類繼承和原型繼承的不同? 希望聽到 4. 函數式編程和面向對象編程的優缺點? ...
閱讀 3044·2021-11-22 09:34
閱讀 3636·2021-08-31 09:45
閱讀 3836·2019-08-30 13:57
閱讀 1670·2019-08-29 15:11
閱讀 1681·2019-08-28 18:04
閱讀 3218·2019-08-28 17:59
閱讀 1558·2019-08-26 13:35
閱讀 2188·2019-08-26 10:12