摘要:小明追女神的故事小明遇到了他的女神,打算送一朵鮮花來表白。剛好小明打聽到他和有一個(gè)共同的好友,于是小明決定讓來替自己來完成這件事。
1.單例模式
單例模式的核心:
(1)確保只有一個(gè)實(shí)例
(2)提供全局訪問
用代理實(shí)現(xiàn)單例模式:
var ProxySingletonCreateDiv = (function(){ var instance; return function( html ){ if ( !instance ){ instance = new CreateDiv( html ); } return instance; } })();
通用的惰性單例模式:創(chuàng)建登陸懸浮窗
//fn保存創(chuàng)建邏輯 //單例模式:只創(chuàng)建一次 var getSingle = function( fn ){ var result; return function(){ return result || ( result = fn .apply(this, arguments ) ); } }; var createLoginLayer = function(){ var div = document.createElement( "div" ); div.innerHTML = "我是登錄浮窗"; div.style.display = "none"; document.body.appendChild( div ); return div; }; var createSingleLoginLayer = getSingle( createLoginLayer ); document.getElementById( "loginBtn" ).onclick = function(){ var loginLayer = createSingleLoginLayer(); loginLayer.style.display = "block"; };2.發(fā)布-訂閱者模式
(1)首先要指定好誰充當(dāng)發(fā)布者
(2)然后給發(fā)布者添加一個(gè)緩存列表,用于存放回調(diào)函數(shù)以便通知訂閱者
(3)最后發(fā)布消息的時(shí)候,發(fā)布者會(huì)遍歷這個(gè)緩存列表,依次觸發(fā)里面存放的訂閱者函數(shù)
var Event = (function(){ var clientList = {}, listen, trigger, remove; listen = function( key, fn ){ if ( !clientList[ key ] ){ clientList[ key ] = []; } clientList[ key ].push( fn ); }; trigger = function(){ var key = Array.prototype.shift.call( arguments ), fns = clientList[ key ]; if ( !fns || fns.length === 0 ){ return false; } for( var i = 0, fn; fn = fns[ i++ ]; ){ fn.apply( this, arguments ); } }; remove = function( key, fn ){ var fns = clientList[ key ]; if ( !fns ){ return false; } if ( !fn ){ fns && ( fns.length = 0 ); }else{ for ( var l = fns.length - 1; l >=0; l-- ){ var _fn = fns[ l ]; if ( _fn === fn ){ fns.splice( l, 1 ); } } } }; return { listen: listen, trigger: trigger, remove: remove } })();
給所有的對(duì)象都動(dòng)態(tài)安裝一個(gè)發(fā)布-訂閱功能:
var installEvent = function( obj ){ for ( var i in event ){ obj[ i ] = event[ i ]; } };3.裝飾著模式
(1)裝飾者模式可以動(dòng)態(tài)的給某個(gè)對(duì)象添加一些額外的職責(zé),而不會(huì)影響從這個(gè)類中派生出的其他對(duì)象。
(2)裝飾者也是包裝器:裝飾者模式將一個(gè)對(duì)象嵌入到另一個(gè)對(duì)象中,實(shí)際上相當(dāng)于這個(gè)對(duì)象被另一個(gè)對(duì)象包裝起來,形成一條包裝鏈。
3-1.在不改變?cè)瓉砗瘮?shù)的情況下給函數(shù)增加新的功能
var a=function(){ alert(1); } var _a = a; a=function(){ _a(); alert(2); }
但是這樣做會(huì)帶來兩個(gè)問題:必須維護(hù)_a這個(gè)中間變量;存在this被劫持的問題
3-2.用AOP裝飾函數(shù)
Function.prototype.before = function( beforefn ){ var __self = this; // 保存原函數(shù)的引用 return function(){ // 返回包含了原函數(shù)和新函數(shù)的"代理"函數(shù) beforefn.apply( this, arguments ); // 執(zhí)行新函數(shù),且保證this 不被劫持,新函數(shù)接受的參數(shù) // 也會(huì)被原封不動(dòng)地傳入原函數(shù),新函數(shù)在原函數(shù)之前執(zhí)行 return __self.apply( this, arguments ); // 執(zhí)行原函數(shù)并返回原函數(shù)的執(zhí)行結(jié)果, // 并且保證this 不被劫持 } } Function.prototype.after = function( afterfn ){ var __self = this; return function(){ var ret = __self.apply( this, arguments ); afterfn.apply( this, arguments ); return ret; } }; //調(diào)用:重寫原來函數(shù) formSubmit = formSubmit.before( validata );4.策略模式
策略模式的定義是:定義一系列的算法,把它們一個(gè)個(gè)封裝起來,并且使它們可以相互替換。
4-1.使用策略模式計(jì)算獎(jiǎng)金
績效為S的人年終獎(jiǎng)金是工資的4倍,績效為A的人年終獎(jiǎng)金是工資的3倍,績效為B的人年終獎(jiǎng)金是工資的2倍
var performanceS = function(){}; performanceS.prototype.calculate = function( salary ){ return salary * 4; }; var performanceA = function(){}; performanceA.prototype.calculate = function( salary ){ return salary * 3; }; var performanceB = function(){}; performanceB.prototype.calculate = function( salary ){ return salary * 2; }; //接下來定義獎(jiǎng)金類Bonus: var Bonus = function(){ this.salary = null; // 原始工資 this.strategy = null; // 績效等級(jí)對(duì)應(yīng)的策略對(duì)象 }; Bonus.prototype.setSalary = function( salary ){ this.salary = salary; // 設(shè)置員工的原始工資 }; Bonus.prototype.setStrategy = function( strategy ){ this.strategy = strategy; // 設(shè)置員工績效等級(jí)對(duì)應(yīng)的策略對(duì)象 }; Bonus.prototype.getBonus = function(){ // 取得獎(jiǎng)金數(shù)額 return this.strategy.calculate( this.salary ); // 把計(jì)算獎(jiǎng)金的操作委托給對(duì)應(yīng)的策略對(duì)象 }; var bonus = new Bonus(); bonus.setSalary( 10000 ); bonus.setStrategy( new performanceS() ); // 設(shè)置策略對(duì)象 console.log( bonus.getBonus() ); // 輸出:40000
4-2.javascript版本的策略模式
var strategies = { "S": function( salary ){ return salary * 4; }, "A": function( salary ){ return salary * 3; }, "B": function( salary ){ return salary * 2; } }; var calculateBonus = function( level, salary ){ return strategies[ level ]( salary ); }; console.log( calculateBonus( "S", 20000 ) ); // 輸出:80000 console.log( calculateBonus( "A", 10000 ) ); // 輸出:30000
通過使用策略模式重構(gòu)代碼,我們消除了原來程序中大片的條件分支代碼。所有和計(jì)算獎(jiǎng)金的邏輯不再放在context中,而是分布在各個(gè)策略對(duì)象中。每個(gè)策略對(duì)象負(fù)責(zé)的算法已被各自封裝在對(duì)象內(nèi)部。當(dāng)我們對(duì)這些策略對(duì)象發(fā)出“計(jì)算獎(jiǎng)金”請(qǐng)求時(shí),它們會(huì)返回各自不同的計(jì)算結(jié)果。
4-3.用策略模式進(jìn)行表單校驗(yàn)
(1)用戶名不能為空
(2)密碼長度不能少于6位
(3)手機(jī)號(hào)碼必須符合格式
5.代理模式
代理模式是為一個(gè)對(duì)象提供一個(gè)代用品或占位符,以便控制對(duì)它的訪問。
5-1.小明追女神的故事
小明遇到了他的女神A,打算送一朵鮮花來表白。剛好小明打聽到他和A有一個(gè)共同的好友B,于是小明決定讓B來替自己來完成這件事。
var Flower = function(){}; var xiaoming = { sendFlower: function( target ){ var flower = new Flower(); target.receiveFlower( flower ); } }; var A = { receiveFlower: function( flower ){ console.log( "收到花 " + flower ); } }; xiaoming.sendFlower( A ); //接下來,我們引入代理B,即小明通過B 來給A 送花: var Flower = function(){}; var xiaoming = { sendFlower: function( target){ var flower = new Flower(); target.receiveFlower( flower ); } }; var B = { receiveFlower: function( flower ){ A.receiveFlower( flower ); 90 第6 章 代理模式 } }; var A = { receiveFlower: function( flower ){ console.log( "收到花 " + flower ); } }; xiaoming.sendFlower( B ); //然后選擇A 心情好的時(shí)候把花轉(zhuǎn)交給A,代碼如下: var Flower = function(){}; var xiaoming = { sendFlower: function( target){ var flower = new Flower(); target.receiveFlower( flower ); } }; var B = { receiveFlower: function( flower ){ A.listenGoodMood(function(){ // 監(jiān)聽A 的好心情 A.receiveFlower( flower ); }); } }; var A = { receiveFlower: function( flower ){ console.log( "收到花 " + flower ); }, listenGoodMood: function( fn ){ setTimeout(function(){ // 假設(shè)10 秒之后A 的心情變好 fn(); }, 10000 ); } }; xiaoming.sendFlower( B ); var myImage = (function(){ var imgNode = document.createElement( "img" ); document.body.appendChild( imgNode ); return { setSrc: function( src ){ imgNode.src = src; } } })();
5-2.保護(hù)代理與虛擬代理
保護(hù)代理:比如B可以幫助A過濾掉一些請(qǐng)求,如送花的人中年齡較大的
虛擬代理:new Flower可能是非常昂貴的,這時(shí)候需要B代理去執(zhí)行,代理B在A心情好的時(shí)候再執(zhí)行。
5-3.虛擬代理實(shí)現(xiàn)圖片預(yù)加載
var myImage = (function(){ var imgNode = document.createElement( "img" ); document.body.appendChild( imgNode ); return function( src ){ imgNode.src = src; } })(); var proxyImage = (function(){ var img = new Image; img.onload = function(){ myImage( this.src ); } return function( src ){ myImage( "file:// /C:/Users/svenzeng/Desktop/loading.gif" ); img.src = src; } })(); proxyImage( "http:// imgcache.qq.com/music// N/k/000GGDys0yA0Nk.jpg" );
縱觀整個(gè)程序,我們并沒有改變或者增加myImage接口,但是通過代理對(duì)象,實(shí)際上是給系統(tǒng)添加了新的行為:給img節(jié)點(diǎn)設(shè)置 src和圖片預(yù)加載這兩個(gè)功能。
5-4.虛擬代理合并http請(qǐng)求
1 2 3 4 5 6 7 8 9
script.js:
var synchronousFile = function( id ){ console.log( "開始同步文件,id 為: " + id ); }; var proxySynchronousFile = (function(){ var cache = [], // 保存一段時(shí)間內(nèi)需要同步的ID timer; // 定時(shí)器 return function( id ){ cache.push( id ); if ( timer ){ // 保證不會(huì)覆蓋已經(jīng)啟動(dòng)的定時(shí)器 return; } timer = setTimeout(function(){ synchronousFile( cache.join( "," ) ); // 2 秒后向本體發(fā)送需要同步的ID 集合 clearTimeout( timer ); // 清空定時(shí)器 timer = null; cache.length = 0; // 清空ID 集合 }, 2000 ); } })(); var checkbox = document.getElementsByTagName( "input" ); for ( var i = 0, c; c = checkbox[ i++ ]; ){ c.onclick = function(){ if ( this.checked === true ){ proxySynchronousFile( this.id ); } } };
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/82818.html
摘要:前言最初,唯有時(shí)光記得。起初,按照自己的學(xué)習(xí)習(xí)慣來,一直秉承著好記性不如爛筆頭的學(xué)習(xí)理念,開始做紙質(zhì)的筆記,累計(jì)了好多本之后,發(fā)現(xiàn)有很多的不便利,例如圖片隨時(shí)要改動(dòng)注明來源等。微信公眾號(hào)微博。 回顧 Retrospect to the past and look into the future 最近在積極地學(xué)習(xí)webview,原本打算整理一下寫成一篇文章。無奈時(shí)間有限,暫時(shí)沒有把握把w...
摘要:前言最初,唯有時(shí)光記得。起初,按照自己的學(xué)習(xí)習(xí)慣來,一直秉承著好記性不如爛筆頭的學(xué)習(xí)理念,開始做紙質(zhì)的筆記,累計(jì)了好多本之后,發(fā)現(xiàn)有很多的不便利,例如圖片隨時(shí)要改動(dòng)注明來源等。微信公眾號(hào)微博。 回顧 Retrospect to the past and look into the future 最近在積極地學(xué)習(xí)webview,原本打算整理一下寫成一篇文章。無奈時(shí)間有限,暫時(shí)沒有把握把w...
摘要:前言最初,唯有時(shí)光記得。起初,按照自己的學(xué)習(xí)習(xí)慣來,一直秉承著好記性不如爛筆頭的學(xué)習(xí)理念,開始做紙質(zhì)的筆記,累計(jì)了好多本之后,發(fā)現(xiàn)有很多的不便利,例如圖片隨時(shí)要改動(dòng)注明來源等。微信公眾號(hào)微博。 回顧 Retrospect to the past and look into the future 最近在積極地學(xué)習(xí)webview,原本打算整理一下寫成一篇文章。無奈時(shí)間有限,暫時(shí)沒有把握把w...
摘要:一開始我以為是的問題,然后重新手寫了一些配置依然會(huì)報(bào)錯(cuò),證明不是的問題。規(guī)則真的很嚴(yán)格。配置問題按照的文檔默認(rèn)是,按照說明應(yīng)該是不會(huì)阻止。 問題 項(xiàng)目一開始使用的是create-react-app創(chuàng)建的,配置的ESLint是用的AlloyTeam的eslint-config-alloy/react, 默認(rèn)配置已經(jīng)很合理了,并且每條配置都有相應(yīng)的說明,只需要再根據(jù)個(gè)人喜好修改一些rule...
摘要:的兼容性由于是現(xiàn)代的技術(shù),以下的古老瀏覽器是不支持的。當(dāng)然也可以手動(dòng)指定文件這些瀏覽器都不能直接使用緩存,即可能會(huì)要求你重新驗(yàn)證,或者直接使用服務(wù)器文件。 親,如果你還在為你沒網(wǎng)打開不網(wǎng)頁而煩惱嗎?親,你還在為你web服務(wù)器復(fù)雜的配置項(xiàng)而蛋疼嗎?不要998,manifest抱回家~manifest自H5橫空出世以來給前端網(wǎng)頁的瀏覽帶來了翻天覆地的變化,以前我們的網(wǎng)頁必須在有網(wǎng)的前提下打...
閱讀 2077·2019-08-30 15:52
閱讀 3063·2019-08-29 16:09
閱讀 1381·2019-08-28 18:30
閱讀 2518·2019-08-26 12:24
閱讀 1162·2019-08-26 12:12
閱讀 2324·2019-08-26 10:45
閱讀 629·2019-08-23 17:52
閱讀 966·2019-08-23 16:03