javascript
javascript OOP(下)(九)
一、javascript模擬重載
java中根據(jù)參數(shù)類型和數(shù)量的區(qū)別來實(shí)現(xiàn)重載,javascript弱類型,沒有直接的機(jī)制實(shí)現(xiàn)重載,javascript中參數(shù)類型不確定和參數(shù)個(gè)數(shù)任意,通過判斷實(shí)際傳入的參數(shù)的個(gè)數(shù)來實(shí)現(xiàn)重載。
<script> function Person() {var args = arguments;if (typeof args[0] === 'object' && args[0]) { //判斷第一個(gè)參數(shù)是否為對(duì)象,進(jìn)行相應(yīng)操作。傳參為空時(shí)typeof null也是object,所以要同時(shí)判斷args[0]不為空if (args[0].name) {this.name = args[0].name;}if (args[0].age) {this.age = args[0].age;}} else {if (args[0]) {this.name = args[0];}if (args[1]) {this.age = args[1];}} }//toString繼承自O(shè)bject,一般的對(duì)象toString會(huì)顯示"[object Object]",沒有什么意義,所以可以重新一下,方便輸出 Person.prototype.toString = function() {return 'name=' + this.name + ',age=' + this.age; }var bosn = new Person('Bosn', 27); bosn.toString(); //name=Bosn,age=27var lxy = new Person({name: 'lxy',age: 25 }); lxy.toString(); //name=lxy,age=25 </script>
二、調(diào)用基類方法
1、調(diào)用基類的方法進(jìn)行初始化
基類人Person
學(xué)生Student
初始化Student的時(shí)候,初始化了className后需要初始化Person部分,可以通過
Person.call(this,name);調(diào)用基類的方法和屬性。
<script> function Person(name){this.name=name; } function Student(name,className){this.className=className;Person.call(this,name); //調(diào)用基類的構(gòu)造器 }var bosn=new Student('Bosn','Network064'); console.log(bosn); </script>輸出時(shí)能夠正確的被初始化。
2、子類覆蓋了基類的方法
Student的init覆蓋了Person的init,初始化Student時(shí)需要初始化Person,通過Person.prototype.init.apply(this,arguments);
<script> Person.prototype.init=function(){};Student.prototype.init=function(){//do sthPerson.prototype.init.apply(this,arguments); } </script>三、鏈?zhǔn)秸{(diào)用
?類似jquery選擇器鏈?zhǔn)秸{(diào)用。
關(guān)鍵要在ClassManager.prototype.addClass操作完成后return this。
<script> function ClassManager(){//構(gòu)造器 }ClassManager.prototype.addClass=function(str){ //在構(gòu)造器上掛載一個(gè)方法,表示addClass console.log('Class:'+str+' added.'); return this;// this總是指向ClassManager的實(shí)例,所以return就實(shí)現(xiàn)了鏈?zhǔn)秸{(diào)用 }var manager=new ClassManager(); manager.addClass('classA').addClass('classB').addClass('classC'); //Class:classA added. //Class:classB added. //Class:classC added.</script>四、抽象類
?沒有機(jī)制,可以進(jìn)行模擬。主要是用throw new Error()。
<script> function DetectorBase(){throw new Error('Abstract class can not be invoked directly!');//在構(gòu)造器里拋一個(gè)異常,防止抽象類被直接調(diào)用 } DetectorBase.detect=function(){console.log('Detection starting...');} DetectorBase.stop=function(){console.log('Detector stopped.');} DetectorBase.init=function(){throw new Error('Error');//想要子類覆蓋而不想被直接調(diào)用的方法,拋出異常 }function LinkDetector(){} //通過Object.create實(shí)現(xiàn)繼承 LinkDetector.prototype=Object.create(DetectorBase.prototype); LinkDetector.prototype.constructor=LinkDetector; </script>五、definePrototype(ES5)
?
<script> //ES5里面對(duì)于屬性有一些getter setter方法,有一些標(biāo)簽 //configurable:能否delete //enumberable:能否for in遍歷 //writable:能否讀寫屬性 //value:記錄屬性值,默認(rèn)為undefine //控制屬性的訪問情況function Person(name){//name可遍歷,不可讀寫,不可刪除Object.defineProperty(this,'name',{value:name,enumerable:true}); } //ARMS_NUM相當(dāng)于定義了一個(gè)常量,可枚舉,不可寫,不可刪除 Object.defineProperty(Person,'ARMS_NUM',{value:2,enumerable:true}); Object.seal(Person.prototype); //Person在初始化之后不想被擴(kuò)展,不想被配置了,用seal方法 Object.seal(Person);function Student(name,className){this.className=className;Person.call(this,name); } Student.prototype=Object.create(Person.prototype); Student.prototype.constructor=Student; </script>六、模塊化
模塊化工具或者說類庫有有seajs,requirejs等。
模塊化的一般形式是:一個(gè)定義了私有變量和函數(shù)的函數(shù);利用閉包創(chuàng)建可以訪問私有變量和函數(shù)的特權(quán)函數(shù);最后返回這個(gè)特權(quán)函數(shù),或者把它們保存到一個(gè)可訪問到的地方。
1、通過返回一個(gè)對(duì)象實(shí)現(xiàn)簡(jiǎn)單模塊化
<script> var moduleA;//只需要把最核心的東西moduleA放到全局作用域 moduleA=function(){var prop=1;function func(){}return{ //func和prop不會(huì)被泄露到全局作用域 func:func,prop:prop} }() //moduleA用立即執(zhí)行的匿名函數(shù) </script>2、通過返回this的方法實(shí)現(xiàn)簡(jiǎn)單模塊化
通過new function(),通過設(shè)置this的值,我們知道通過new調(diào)用最后會(huì)返回this,除非你return的是一個(gè)對(duì)象。
<script> //通過new默認(rèn)返回this的方法 va moduleA; moduleA=new function(){var prop=1;function func(){}this.func=func;this.prop=prop; } </script>3、模塊化應(yīng)用【update20170307】
模塊化可以摒棄全局變量的使用。促進(jìn)了信息隱藏和其他優(yōu)秀的設(shè)計(jì)實(shí)踐。對(duì)于應(yīng)用程序的封裝,或者構(gòu)造其他單例對(duì)象,模塊模式非常有效。
模塊模式也可以用來產(chǎn)生安全的對(duì)象。
例:構(gòu)造一個(gè)用來產(chǎn)生序列號(hào)的對(duì)象。
<script> var serial_maker=function(){ /*返回一個(gè)用來產(chǎn)生唯一字符串的對(duì)象。 唯一字符串由兩部分組成:前綴+序列號(hào)。 該對(duì)象包含一個(gè)設(shè)置前綴的方法,一個(gè)設(shè)置序列號(hào)的方法和一個(gè)產(chǎn)生唯一字符串的gensym方法。 */ var prefix=''; var seq=0; return{set_prefix:function(p){prefix=String(p);},set_seq:function(s){seq=s;},gensym:function(){var result=prefix+seq;seq+=1;return result;} } }; var seqer=serial_maker(); seqer.set_prefix('Q'); seqer.set_seq(1000); var unique; unique=seqer.gensym(); console.log(unique);//unique是"Q1000" unique=seqer.gensym(); console.log(unique);//unique是"Q1001"</script>seqer()的3個(gè)方法都沒有用到this或者that,因此沒有辦法損害seqer。除非調(diào)用對(duì)應(yīng)的方法,否則沒法改變prefix或seq的值。
seqer對(duì)象是可變的,所以它的方法可能會(huì)被替換掉,但替換后的方法依然不能訪問私有變量。
比如:
seqer.gensym=function(){var result=prefix+seq;seq+=3;console.log(seq);return result; }就會(huì)報(bào)錯(cuò),因?yàn)樘鎿Q后的方法不能訪問私有變量。
seqer就是一組函數(shù)的集合,而且那些函數(shù)被授予特權(quán),擁有使用或修改私有狀態(tài)的能力。
如果我們把seqer.gensym作為一個(gè)值傳遞給第三方函數(shù),那個(gè)函數(shù)能用它產(chǎn)生唯一字符串,卻不能通過修改它來改變prefix或seq的值。
參考:
js模塊化歷程
http://www.cnblogs.com/lvdabao/p/js-modules-develop.html
寫了十年JS卻不知道模塊化為何物?
https://blog.wilddog.com/?p=587
?深入淺出ES6(十三):類 Class
http://www.infoq.com/cn/articles/es6-in-depth-classes/
?
本文作者starof,因知識(shí)本身在變化,作者也在不斷學(xué)習(xí)成長(zhǎng),文章內(nèi)容也不定時(shí)更新,為避免誤導(dǎo)讀者,方便追根溯源,請(qǐng)諸位轉(zhuǎn)載注明出處:http://www.cnblogs.com/starof/p/4904929.html有問題歡迎與我討論,共同進(jìn)步。
總結(jié)
以上是生活随笔為你收集整理的javascript OOP(下)(九)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 创建laravel项目
- 下一篇: ImageView的scaleType详