摘要:設(shè)計(jì)模式是一套可復(fù)用的,被眾人知曉,經(jīng)過(guò)編目分明的,經(jīng)驗(yàn)的總結(jié)。創(chuàng)建類安全工廠判斷是否調(diào)用關(guān)鍵字設(shè)計(jì)模式設(shè)計(jì)模式運(yùn)算符可以用來(lái)判斷某個(gè)構(gòu)造函數(shù)的屬性所指向的對(duì)象是否存在于另外一個(gè)要檢測(cè)對(duì)象的原型鏈上。
設(shè)計(jì)模式
是一套可復(fù)用的,被眾人知曉,經(jīng)過(guò)編目分明的,經(jīng)驗(yàn)的總結(jié)。
作用:使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性
創(chuàng)建型設(shè)計(jì)模式:解決對(duì)象在創(chuàng)建時(shí)產(chǎn)生的一系列問(wèn)題。
結(jié)構(gòu)型設(shè)計(jì)模式:解決類或?qū)ο笾g組合時(shí)產(chǎn)生的一系列問(wèn)題
行為型設(shè)計(jì)模式:解決類或?qū)ο笾g的交互以及職責(zé)分配的一些列問(wèn)題
創(chuàng)建型模式:?jiǎn)卫J?、抽象工廠模式、建造者模式、工廠模式、原型模式。 (5)
結(jié)構(gòu)型模式:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。(7)
行為型模式:模版方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式(Interpreter模式)、狀態(tài)模式、策略模式、職責(zé)鏈模式(責(zé)任鏈模式)、訪問(wèn)者模式。(11)
設(shè)計(jì)模式:是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過(guò)分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié),它強(qiáng)調(diào)的是一個(gè)設(shè)計(jì)問(wèn)題的解決方法
框架:軟件框架是項(xiàng)目軟件開發(fā)過(guò)程中提取特定領(lǐng)域軟件的共性部分形成的體系結(jié)構(gòu),不同領(lǐng)域的軟件項(xiàng)目有著不同的框架類型??蚣懿皇乾F(xiàn)成可用的應(yīng)用系統(tǒng)。而是一個(gè)半成品,提供了諸多服務(wù),開發(fā)人員進(jìn)行二次開發(fā),實(shí)現(xiàn)具體功能的應(yīng)用系統(tǒng)。 ( 只有基礎(chǔ)公共代碼,而沒(méi)有業(yè)務(wù)邏輯的產(chǎn)品,就是框架。)
架構(gòu):簡(jiǎn)單的說(shuō)架構(gòu)就是一個(gè)藍(lán)圖,是一種設(shè)計(jì)方案,將客戶的不同需求抽象成為抽象組件,并能夠描述這些抽象組件之間的通信和調(diào)用,偏重于設(shè)計(jì)??蚣鼙燃軜?gòu)更具體,更偏重于技術(shù)
工具庫(kù):是類(方法)的集合,這些類之間可能是相互獨(dú)立的??梢灾苯诱{(diào)用它,而不必再寫一個(gè)??蚣芤餐穷悾ǚ椒ǎ┑募?;但框架中的各個(gè)類并不是孤立的,而框架中的業(yè)務(wù)邏輯代碼是將不同的類“連”在一起,在它們之間建立協(xié)作關(guān)系
設(shè)計(jì)模式研究的是針對(duì)單一問(wèn)題的設(shè)計(jì)思路和解決方法,一個(gè)模式可應(yīng)用于不同的框架和被不同的語(yǔ)言所實(shí)現(xiàn);而框架則是一個(gè)應(yīng)用的體系結(jié)構(gòu),是一種或多種設(shè)計(jì)模式和代碼的混合體雖然它們有所不同,但卻共同致力于使人們的設(shè)計(jì)可以被重用,在思想上存在著統(tǒng)一性的特點(diǎn),因而設(shè)計(jì)模式的思想可以在框架設(shè)計(jì)中進(jìn)行應(yīng)用。
工廠模式 簡(jiǎn)單工廠定義:用來(lái)創(chuàng)建一種類型的產(chǎn)品實(shí)例,所以他創(chuàng)建的對(duì)象單一
特點(diǎn):
通過(guò)將創(chuàng)建過(guò)程寄生在工廠內(nèi),可以解決全局變量污染問(wèn)題。
創(chuàng)建的產(chǎn)品對(duì)象單一。
對(duì)工廠進(jìn)行改造可以適應(yīng)不同的需求。
批量生產(chǎn)
第一種:
在外部創(chuàng)建一個(gè)批量生產(chǎn)的工廠,然后再內(nèi)部調(diào)用工廠,它的問(wèn)題是需要另外創(chuàng)建一個(gè)工廠
第二種:
通過(guò)在工廠方法內(nèi)部進(jìn)行分支判斷,決定創(chuàng)建單個(gè)產(chǎn)品或者品量單品。
這種方式在工廠內(nèi)部調(diào)用該廠,依賴了工廠名稱。
第三種:
通過(guò)在工廠方法內(nèi)部進(jìn)行分支判斷,決定創(chuàng)建單個(gè)產(chǎn)品或者品量單品。
這種方式在工廠內(nèi)部調(diào)用了,arguments.callee解決了對(duì)工廠名稱的依賴。
通過(guò)對(duì)寄生在工廠內(nèi)部的對(duì)象增添方法屬性,使在不改變?cè)惖幕A(chǔ)上,完成對(duì)類的拓展
在工廠內(nèi)部實(shí)例化類 這一步叫做寄生
對(duì)實(shí)例化的類拓展方法和屬性 這一步叫做增強(qiáng)
將這個(gè)對(duì)象返回。 這一步是工廠。
安全工廠模式
又叫:安全類
特點(diǎn),不論在調(diào)用的時(shí)候有沒(méi)有new關(guān)鍵字,得到的結(jié)果都是一樣的。
判斷this是否是只想當(dāng)前對(duì)象的。通過(guò)instanceof
如果是通過(guò)new關(guān)鍵字創(chuàng)建的,就直接對(duì)this賦值
如果不是,主動(dòng)創(chuàng)建,并返回該實(shí)例。
//創(chuàng)建 Book類 //安全工廠 var Book = function ( title ) { //判斷是否調(diào)用 new 關(guān)鍵字 if ( this instanceof Book ) { this.title = title; } else { return new Book(title); } } //var b1 = new Book("設(shè)計(jì)模式1"); var b2 = Book("設(shè)計(jì)模式2"); //console.log( b1 ,b1 instanceof Book ); //true console.log( b2 ,b2 instanceof Book ); //true
instanceof運(yùn)算符可以用來(lái)判斷某個(gè)構(gòu)造函數(shù)的prototype屬性所指向的對(duì)象是否存在于另外一個(gè)要檢測(cè)對(duì)象的原型鏈上。
工廠方法通過(guò)對(duì)產(chǎn)品類的抽象使其創(chuàng)建業(yè)務(wù)主要負(fù)責(zé)用于創(chuàng)建多類產(chǎn)品的實(shí)例
特點(diǎn):
創(chuàng)建多類對(duì)象
也是對(duì)類的再封裝
步驟:
聲明參數(shù)
循環(huán)創(chuàng)建類
對(duì)類的添加方法
將實(shí)例化對(duì)象返回
原型模式
通過(guò)將對(duì)象的原型指向類的原型實(shí)現(xiàn)對(duì)該對(duì)象原型的屬性與方法的共享。
var Rect = function( x,y ){ //繼承 Base.apply(this,arguments); this.dom.className = "rect"; } Rect.prototype = new Base();
原型模式一種創(chuàng)建型設(shè)計(jì)模式
它基于javascript原型鏈原理實(shí)現(xiàn)的
是一種組合式繼承
對(duì)于處理復(fù)雜的類,通過(guò)提取公共部分實(shí)現(xiàn)對(duì)類優(yōu)化
只能創(chuàng)建一個(gè)實(shí)例, 把所有代碼和數(shù)據(jù)組織到一個(gè)地方. 全局的資源,公共的數(shù)據(jù), 組織到一起.統(tǒng)一的管理.
單體模式 一般不采用new 關(guān)鍵字. 已經(jīng)存在了對(duì)象.
主要用來(lái) 劃分命名空間(區(qū)分代碼,降低耦合性)
var Singleton={ attr1: true, attr2: 10, method1: function(){ alert(this.attr1); }, method2: function(){ alert("方法2"); } }惰性單例
借用閉包創(chuàng)建單體 閉包主要的目的:就是保護(hù)數(shù)據(jù),不受外界所干擾.
通過(guò)閉包將我們的single封裝起來(lái),避免外部訪問(wèn)而實(shí)例化,這樣可保證實(shí)例化一次,閉包的返回函數(shù)的作用域在閉包里面,所以可以訪問(wèn)到single類對(duì)其實(shí)例化,這樣在執(zhí)行LazySingle才會(huì)對(duì)single類實(shí)例化
特點(diǎn):
只能被實(shí)例化一次
推遲了實(shí)例化時(shí)間
var _interface = null; var LazySingle = (function () { var Signle = function () { // do } Signle.prototype = { version: 2, sayHello: function () { console.log("1"); } } return function () { if ( !_interface ) { _interface = new Signle(); } return _interface; } })() var s = LazySingle(); s.sayHello();分支單體
判讀程序的分支 --> 瀏覽器差異檢測(cè)
var Slington = (function(){ var def = true; var More = function(){ var objA = { //火狐瀏覽器 內(nèi)部的一些配置 attr1: "ff attr1", //屬性1 //方法1 } var objB = { //ie瀏覽器 內(nèi)部的一些配置 attr2: "ie attr1", //屬性1 //方法1 } } return (def) ? new More().objA : new More().objB; })();適配器模式
將一個(gè)類(對(duì)象)的接口(屬性或者方法)轉(zhuǎn)化成另一個(gè)類(對(duì)象)的接口,以滿足用戶的需要,使類(對(duì)象)之間接口的不兼容問(wèn)題得以解決。
對(duì)被適配的數(shù)據(jù)的一個(gè)分解再封裝的一個(gè)過(guò)程。
這個(gè)過(guò)程中會(huì)造成一定的開銷。但遠(yuǎn)比更改原有業(yè)務(wù)邏輯成本低。
需要dataAdaptor函數(shù)中有適配映射表
function DealData ( arr ) { var div = document.createElement("div"); var img = new Image(); var a = document.createElement("a"); var p = document.createElement("p"); img.src = arr[1]; a.href = arr[0]; p.innerHTML = arr[2]; a.appendChild(p); a.appendChild(img); div.appendChild(a); document.body.appendChild(div); } //適配器 function DataAdaptor ( data ) { var arr = []; //適配映射表 var map = { "src": 1, "href": 0, "title": 2 } for ( var i in map ) { //把第三方數(shù)據(jù)源中的數(shù)據(jù),放到自己數(shù)據(jù)中的數(shù)組中的相應(yīng)位置 //map[i] -> 自己數(shù)據(jù)源中的位置 //i -> 第三方數(shù)據(jù)源中的屬性 arr[map[i]] = data[i]; } //匹配出來(lái)后的數(shù)據(jù) // arr[0] = data.href // arr[1] = data.src // arr[2] = data.title return arr; } //第三方提供數(shù)據(jù) // obj.href : 鏈接地址 // obj.src : 圖片地址 // obj.title : 圖片標(biāo)題 $.get("xxx.json",function ( oD ) { if ( oD && oD.errno === 0 ) { var newRes = new DataAdaptor( oD.data ); DealData(newRes); } })參數(shù)適配
使用繼承
使用 || 運(yùn)算符
function extend ( targetObj,obj ) { for ( var i in obj ) { targetObj[i] = obj[i]; } return targetObj; } var Button = function ( param ) { var btn = document.createElement("button"); //默認(rèn)參數(shù) var def = { "background": "tan", "color": "yellow", "fontSize": "12px", "text": "按鈕" } // 適配用戶傳遞的參數(shù)與默認(rèn)的參數(shù) var def1 = extend(def,param); for ( var i in def1 ) { if ( i === "text" ) { btn.innerHTML = def1[i]; } else { btn.style[i] = def1[i]; } } document.body.appendChild(btn); } Button({"background": "deeppink"});組合模式
部分整體模式,將對(duì)象表示成樹形結(jié)構(gòu),表示部分整體關(guān)系。所以部分與整體的行為習(xí)慣達(dá)到一致型。
組合模式中只有兩種類型對(duì)象,組合對(duì)象,葉子對(duì)象
創(chuàng)建類的步驟:
構(gòu)造函數(shù)
構(gòu)造函數(shù)繼承
保留參數(shù)
初始化數(shù)據(jù)
原型式繼承,繼承基類方法
重寫init方法
添加其他方法
它是將整體分解成為一個(gè)個(gè)部分,再有部分重新拼裝成一個(gè)整體。部分分解的也多,整合結(jié)果也就越多。
它的部分與整體之間具有行為的一致性。
部分拼裝成整體的過(guò)程具有多樣性
叫消息系統(tǒng),消息機(jī)制,或者發(fā)布訂閱模式。通過(guò)消息系統(tǒng)實(shí)現(xiàn)對(duì)象或者類之間的解耦。
解決是一種依賴關(guān)系,
解決了,主體與觀察者之間的一種依賴關(guān)系。
被觀察者對(duì)象或者類也可以是觀察者,觀察者也可以是被觀察者
觀察者內(nèi)部變化不會(huì)影響到被觀察者,反過(guò)來(lái)一樣
var Observer = (function () { var __msg = {}; return { //添加訂閱者 //@param {String} type 訂閱者名字 //@param {Function} fn 執(zhí)行函數(shù) add: function ( type,fn ) { if ( __msg[type] ) { __msg[type].push(fn); } else { __msg[type] = [fn]; } return this; }, //執(zhí)行回調(diào)函數(shù) //@param {String} type fire: function ( type,data ) { if ( __msg[type] ) { var e = data for ( var i=0; i<__msg[type].length; ++i ) { __msg[type][i](e); } } return this; }, // 移除回調(diào)函數(shù) // @param {String} type // @param {String} fnName remove: function ( type,fnName ) { if ( __msg[type] ) { for ( var i = __msg[type].length-1; i>=0; --i ) { if ( __msg[type][i] === fnName ) { __msg[type].splice(i,1); } } } return this; } } })()策略模式
封裝一組算法,使其可以互相替換,這組算法本身具有獨(dú)立性,不受客戶端影響。
特點(diǎn):
它是行為型模式
每種都是獨(dú)立的,所他們之間可以相互替換
他解決是使用者與策略算法之間的耦合
算是是獨(dú)立的方便我們進(jìn)行單測(cè)
算法在使用時(shí)候的過(guò)程是不一樣的,但結(jié)果是一樣的
tween中使用的是策略模式,價(jià)格算法,表單驗(yàn)證.
價(jià)格:
淘寶價(jià):
//表單驗(yàn)證 var InputStrategy = (function () { //策略模型 var strategy = { //判斷是否為空 "notNull": function ( val ) { return /^s*$/g.test(val) ? "輸入的內(nèi)容不能為空" : ""; }, //判斷是否是數(shù)字 "isNumber": function ( val ) { return /^-?[d]+(.[d])?$/.test(val) ? "" : "輸入的不是一個(gè)正確的數(shù)字"; }, //判斷電話格式 010-12345678 1234-1234567 "isTelephoneNumber": function ( val ) { return /^[d]{3}-[d]{8}$|^[d]{4}-[d]{7}$ /.test(val) ? "" : "請(qǐng)輸入一個(gè)正確的電話號(hào)碼"; } } return { //檢測(cè)表單輸入的文本內(nèi)容是否正確 //@param {String} val 檢測(cè)文本 //@param {String} type 檢測(cè)算法 check: function ( val,type ) { if ( strategy[type] ) { return strategy[type](val); } else { return "沒(méi)有該算法"; } } } })() //策略名稱 與 頁(yè)面中的表單的 映射表 var arr = ["notNull", "isNumber", "isTelephoneNumber"]; for ( var i=1; i<4; i++ ) { checkInp( "inp"+i ,"err"+i,arr[i-1] ); } //執(zhí)行 檢測(cè)表單 function checkInp ( inpId,errId,type ) { //添加監(jiān)聽 document.getElementById(inpId).onblur = function ( ev ) { var val = ev.target.value; var reslut = InputStrategy.check( val,type ); if ( reslut ) { document.getElementById(errId).innerHTML = reslut; } else { document.getElementById(errId).innerHTML = ""; } } }命令模式
將請(qǐng)求與實(shí)現(xiàn)解耦并封裝,實(shí)現(xiàn)請(qǐng)求對(duì)客戶端實(shí)現(xiàn)參數(shù)化。
命令模式渲染視圖頁(yè)面中有好多數(shù)據(jù)源,要對(duì)這些數(shù)據(jù)源渲染頁(yè)面,傳統(tǒng)方式,渲染頁(yè)面時(shí)候,將視圖,數(shù)據(jù),業(yè)務(wù)耦合在一起了,不利于開發(fā),所以要將這些實(shí)現(xiàn)東西提取出來(lái)封裝成一個(gè)個(gè)命令供使用,來(lái)實(shí)現(xiàn)代碼復(fù)用,并簡(jiǎn)化的創(chuàng)建操作
命令模式解決了命令的發(fā)起者與命令的實(shí)現(xiàn)者之間的耦合
命令的發(fā)起者(調(diào)用命令的時(shí)候) 不必去了解命令是如何實(shí)現(xiàn)的以及命令是如何運(yùn)行的。
所有的在使用具有一致性。
命令模式在一定程度上簡(jiǎn)化了操作。
canvas繪圖的 上下文 ctx 一些問(wèn)題
模塊外界訪問(wèn)不到 ctx
ctx很重要,不論操作都需要使用這個(gè)變量
一旦更改這個(gè)變量,會(huì)造成很嚴(yán)重的后果,造成原有功能失效。
把ctx封裝成內(nèi)部方法。 封裝成 cmd 對(duì)象下的方法, 在excute 命令執(zhí)行方法中匹配 cmd 中的方法
迭代器模式 數(shù)組迭代器
// 遍歷 // arr 遍歷的函數(shù) // cb function each ( arr,cb ) { for ( var i=0,len=arr.length; i委托模式對(duì)象迭代器 //obj 要被遍歷的對(duì)象 //cb 遍歷回調(diào)函數(shù) function each( obj,cb ){ for( var i in obj ){ cb && cb.call(obj,obj[i],i); } }function each (obj, fn) { // obj是一個(gè)數(shù)組時(shí)候 if (obj instanceof Array) { //判斷是否是數(shù)組 //迭代數(shù)組 for (var i = 0, len = obj.length; i < len; i++) { fn(obj[i], i, obj) } // obj是一個(gè)對(duì)象 } else { // 迭代對(duì)象 for (var i in obj) { fn(obj[i], i, obj) } } }面向?qū)ο笾械牡?/b>面向?qū)ο笾杏袝r(shí)需要遍歷實(shí)例化對(duì)象中的自身屬性,過(guò)濾掉原型上的屬性,可以通過(guò) hasOwnPrototy 來(lái)實(shí)現(xiàn)
// 遍歷實(shí)例化對(duì)象自身的屬性,過(guò)濾掉原型上的屬性 // obj 實(shí)例化對(duì)象 // cb 回調(diào)函數(shù) function each ( obj,cb ) { for ( var i in obj ) { if ( obj.hasOwnPrototy(i) ) { cb && cb.call(obj,obj[i],i); } } }迭代器的特點(diǎn)
本身并沒(méi)有刪除循環(huán)語(yǔ)句,只是將循環(huán)語(yǔ)句轉(zhuǎn)移到迭代器的內(nèi)部,
迭代器模式中,數(shù)據(jù)對(duì)象內(nèi)部的結(jié)構(gòu),只需要關(guān)注處理函數(shù)。
移出了循環(huán)語(yǔ)句,使得代碼看著更清晰
迭代器模式是將數(shù)據(jù)源于處理函數(shù)之間的解耦
DOM迭代器
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
是將多個(gè)對(duì)象接收并處理的請(qǐng)求,統(tǒng)一委托給另外一個(gè)對(duì)象處理
委托模式解決事件數(shù)量問(wèn)題解決事件綁定數(shù)量的問(wèn)題,為一堆元素綁定事件,通過(guò)for循環(huán)遍歷綁定,無(wú)形中綁定了n個(gè)事件,這樣在內(nèi)存中造成一定的開銷。
可以通過(guò)這些元素公共的父元素,對(duì)其綁定事件,通過(guò)e.target事件觸發(fā)的目標(biāo)元素的某些屬性來(lái)確認(rèn)是哪些元素需要綁定事件來(lái)解決上面的問(wèn)題。
通??梢耘袛?strong>元素的名稱,類名,id,及其屬性。
通過(guò)對(duì)子元素的某些特性判斷,來(lái)實(shí)現(xiàn)對(duì)該元素的事件的綁定。
var oUl = document.getElementsByTagName("ul")[0]; var li = oUl.getElementsByTagName("li"); oUl.addEventListener("click",function ( e ) { // console.log( e ); if ( e.target.tagName.toLocaleLowerCase() == "li" ) { e.target.style.background = "pink"; } },false);未來(lái)元素事件綁定問(wèn)題
傳統(tǒng)式方式通過(guò)for循環(huán),只能對(duì)現(xiàn)用元素進(jìn)行事件綁定,當(dāng)需要在后面添加新的元素的時(shí)候,該方案不能對(duì)新元素綁定事件。
委托模式,通過(guò)將子元素的事件綁定委托給父元素,事件對(duì)子元素事件綁定的效果,這樣,在父元素中添加新的子元素,同樣可以獲取綁定事件的效果
var oUl = document.getElementsByTagName("ul")[0]; var li = oUl.getElementsByTagName("li"); oUl.addEventListener("click",function ( e ) { // console.log( e ); if ( e.target.tagName.toLocaleLowerCase() == "li" ) { e.target.style.background = "pink"; } },false); var oLi = document.createElement("li"); oLi.innerHTML = "11"; oUl.appendChild(oLi);jQuery事件委托
jQuery中給我提供了一個(gè)專用來(lái)是做事件委托事件綁定方法,delegate,它實(shí)質(zhì)上是通過(guò)on方法實(shí)現(xiàn)的
內(nèi)存外泄
在低版本IE瀏覽器中,內(nèi)存只會(huì)清理哪些沒(méi)有被javascript引用的dom元素,所以在對(duì)元素定義事件時(shí)候,如果將元素清理一定要將該元素綁定的事件解除,因此要在事件內(nèi)部顯性清除事件綁定,但這就要寫在原有事件內(nèi)部,
var oDiv = document.getElementsByTagName("div")[0]; var oBtn = document.getElementsByTagName("button")[0]; oBtn.onclick = function () { oBtn.onclick = null; //手動(dòng)清除事件綁定 oDiv.innerHTML = "info"; }
更好的解決方案是對(duì)該元素的父元素委托綁定事件,這樣當(dāng)清理該元素時(shí)候,由于沒(méi)有事件的綁定,該元素即會(huì)被清理
var oDiv = document.getElementsByTagName("div")[0]; var oBtn = document.getElementsByTagName("button")[0]; oDiv.onclick = function ( ev ) { if ( ev.target.tagName.toLocaleLowerCase() === "button" ) { oDiv.innerHTML = "info"; } }數(shù)據(jù)分發(fā)
動(dòng)態(tài)頁(yè)面中,頁(yè)面中的每個(gè)模塊會(huì)對(duì)應(yīng)一個(gè)數(shù)據(jù)請(qǐng)求,然而如果頁(yè)面中的這類模塊很多,就要發(fā)送多個(gè)請(qǐng)求,但是并發(fā)請(qǐng)求的個(gè)數(shù)是有限的 ,因此后面的請(qǐng)求就會(huì)被堵塞,為了解決這類問(wèn)題,可以將這些請(qǐng)求委托給父請(qǐng)求統(tǒng)一處理,當(dāng)接收數(shù)據(jù)后,解析數(shù)據(jù),并派發(fā)給各個(gè)子模塊中,供其使用
//對(duì)每個(gè)模塊進(jìn)行封裝 var DealStrategy = { "banner": function ( data ) { $(".banner").html(data); }, "article": function ( data ) { $(".article").html(data); }, "aside": function ( data ) { $(".aside").html(data); } } function Deal ( data ) { for ( var i in data ) { DealStrategy[i](data[i]); } } //發(fā)出 get 請(qǐng)求 $.get("data/all.json",function ( res ) { if ( res.errno === 0 ) { Deal( res.data ); } });節(jié)流模式
對(duì)重復(fù)的業(yè)務(wù)邏輯進(jìn)行節(jié)流控制,執(zhí)行最后一次操作并取消其他操作,以提高性能。
特點(diǎn):
通過(guò)計(jì)時(shí)器延遲程序的執(zhí)行
通過(guò)計(jì)時(shí)器,使程序異步執(zhí)行,避免開銷大的程序造成的堵塞
條件:
程序可控:即取消后是否可以繼續(xù)執(zhí)行
異步執(zhí)行:即程序是否可以異步執(zhí)行
節(jié)流器通過(guò)jQuery的stop方法禁止動(dòng)畫的排隊(duì),但是對(duì)于滾動(dòng)這種高頻事件,每次執(zhí)行都會(huì)添加動(dòng)畫
通過(guò)節(jié)流模式,短時(shí)間內(nèi)觸發(fā)多次動(dòng)畫時(shí),前面動(dòng)畫被取消添加,這樣只執(zhí)行最后一次,來(lái)提高性能
節(jié)流器通常提供兩種使用方式
觸發(fā)操作
清除操作
//對(duì)重復(fù)的業(yè)務(wù)邏輯,通常執(zhí)行最后一個(gè),取消前面的業(yè)務(wù)邏輯,來(lái)實(shí)現(xiàn)業(yè)務(wù)邏輯的優(yōu)化。 //高頻事件, mousemove ,window.onscorll var Throttle = function () { var isClear = arguments[0] , fn; if ( isClear !== "true" ) { // 觸發(fā)操作 // @param[0] [Function] 表示函數(shù)的名稱 // @param[1] [Object] 配置項(xiàng) //觸發(fā)操作 fn = isClear; var o = arguments[1] || {}; var obj = { time: o.time || 200, context: o.context || null, data: o.data || null }; //配置項(xiàng) //設(shè)表先關(guān) fn._throttle && clearTimeout(fn._throttle); fn._throttle = setTimeout(function(){ fn.call(obj.context,obj.data); },obj.time); } else { // 清除操作 // @param[0] [Boolean] 表示是否取消操作. true 取消 // @param[1] [Function] 取消的函數(shù)名稱 //取消操作 fn = arguments[1]; //清除定時(shí)器 fn._throttle && clearTimeout(fn._throttle); } } function goBack(){ console.log(1); } //觸發(fā) Throttle(goBack,{time: 500,data: {msg: "hello"}}); //清除操作 // Throttle(true,goBack);統(tǒng)計(jì)節(jié)流
統(tǒng)計(jì)是什么,為什么要做統(tǒng)計(jì)?
統(tǒng)計(jì)是為了了解用戶對(duì)頁(yè)面使用習(xí)慣或者使用方式的,要為頁(yè)面添加統(tǒng)計(jì)來(lái)幫助分析用戶的使用行為
統(tǒng)計(jì)的實(shí)現(xiàn)
當(dāng)用戶觸發(fā)一次交互的時(shí)候,想向服務(wù)器端發(fā)送一條信息,將其記錄下來(lái),保存在服務(wù)器中。
前端的一些交互,有時(shí)候是不需要向服務(wù)器端發(fā)送請(qǐng)求的,此時(shí),服務(wù)器端是不知道這些行為的,所以要向服務(wù)器端發(fā)送請(qǐng)求告知
統(tǒng)計(jì)請(qǐng)求方面的考慮
post請(qǐng)求要比get請(qǐng)求發(fā)送的時(shí)處理事情要多,在做統(tǒng)計(jì)的時(shí)候就不考慮post請(qǐng)求
Ajax可以發(fā)送get請(qǐng)求,但是要寫好多邏輯代碼
請(qǐng)求文檔是一個(gè)get請(qǐng)求,但是請(qǐng)求過(guò)來(lái)的頁(yè)面中的信息量比較多
script標(biāo)簽也是get請(qǐng)求,
link標(biāo)簽也是一個(gè)get請(qǐng)求
img標(biāo)簽也是get請(qǐng)求
相比較這幾種,img的發(fā)送成本更低一些,在發(fā)送統(tǒng)計(jì)請(qǐng)求的時(shí)候,用img(0字節(jié)的圖片作為中轉(zhuǎn)發(fā)送get請(qǐng)求)的get請(qǐng)求
請(qǐng)求節(jié)流
頁(yè)面中的一些高頻事件,做統(tǒng)計(jì)的時(shí)候,會(huì)不停的發(fā)送統(tǒng)計(jì),由于請(qǐng)求的并發(fā)次數(shù)是有限的 ,不能同時(shí)發(fā)送這么多的請(qǐng)求。這回造成后面資源的加載延遲,要對(duì)這些統(tǒng)計(jì)做節(jié)流處理
var img = new Image(); function sendLog ( val ) { var reslutStr = ""; for ( var i in val ) { reslutStr += "&" + i + "=" + val[i]; } img.src = "a.jpg?" + reslutStr; }
統(tǒng)計(jì)的拼接
一條統(tǒng)計(jì) ?Type=click&date=123
將兩條統(tǒng)計(jì)拼接在一起 ?Type=click&dat2=123&type=mouseover&date=234,這樣的化出現(xiàn)相同的字段了,不能這么拼接,
可以將一條統(tǒng)計(jì)作為一個(gè)值: ?Log1=typeclick|date123 //將一條數(shù)據(jù),作為請(qǐng)求的 一個(gè) id.
拼接兩個(gè)統(tǒng)計(jì)的時(shí)候,就可以?Log1=typeclick|date123&log2=typemouserover|date234
//節(jié)流處理: 當(dāng)發(fā)送第一個(gè)請(qǐng)求的時(shí)候,將其緩存下來(lái),當(dāng)其觸發(fā)的次數(shù)達(dá)到規(guī)定的次數(shù)再發(fā)送 //想緩存,需要有緩存容器, dataCache 次數(shù),需要有次數(shù)的規(guī)定。maxNum //將一條數(shù)據(jù),作為請(qǐng)求的 一個(gè) id. var LogPack = (function () { var dataCache = []; //緩存容器 var maxNum = 10; //緩存的次數(shù) var oImg = new Image(); //請(qǐng)求的觸發(fā)器 var itemSplit = "|"; var keyValSplit = "*"; //發(fā)送統(tǒng)計(jì) function sendLog () { var logs = dataCache.splice(0,10); var str = ""; for ( var i=0; imaxNum ) { //發(fā)送 sendLog(); } }; })() //觸發(fā) var oBtn = document.getElementById("btn"); oBtn.onmousemove = function () { LogPack({ type: "onmousemove", date: new Date().getTime() }); } // oBtn.onmouseover = function () { LogPack({ type: "onmouseover", date: new Date().getTime() }); }
//發(fā)送結(jié)果
Model(模型)表示應(yīng)用程序核心(比如數(shù)據(jù)庫(kù)記錄列表)。
是應(yīng)用程序中用于處理應(yīng)用程序數(shù)據(jù)邏輯的部分。通常模型對(duì)象負(fù)責(zé)在數(shù)據(jù)庫(kù)中存取數(shù)據(jù)。
View(視圖)顯示數(shù)據(jù)(數(shù)據(jù)庫(kù)記錄)。
是應(yīng)用程序中處理數(shù)據(jù)顯示的部分。通常視圖是依據(jù)模型數(shù)據(jù)創(chuàng)建的
Controller(控制器)處理輸入(寫入數(shù)據(jù)庫(kù)記錄)
是應(yīng)用程序中處理用戶交互的部分。通??刂破髫?fù)責(zé)從視圖讀取數(shù)據(jù),控制用戶輸入,并向模型發(fā)送數(shù)據(jù)。
Model,頁(yè)面數(shù)據(jù)的存儲(chǔ)操作
View,渲染出可視(給人看)的頁(yè)面操作
Controller,頁(yè)面的交互對(duì)視圖的更改以及對(duì)數(shù)據(jù)的更改
View層通過(guò)Model渲染數(shù)據(jù),所以View層可以訪問(wèn)Model層
Controller層可以對(duì)Model寫入讀取數(shù)據(jù),所以Controller可以訪問(wèn)Model層
Controller層可以對(duì)View層打開彈層,浮層等交互,所以Controller可以訪問(wèn)View層
在前端的框架中,很多框架是基于MVC模式實(shí)現(xiàn),比如BackBone
它將MVC進(jìn)行了一些改造,比如它允許Model層可以訪問(wèn)View層,實(shí)現(xiàn)數(shù)據(jù)層的更新通知View層視圖的渲染
通常一個(gè)模塊對(duì)應(yīng)一個(gè)控制器,一個(gè)模型,一個(gè)視圖,那么如果將頁(yè)面所有模塊中的視圖,控制器模型放在一起,邏輯比較混亂,為了管理方便,將一個(gè)模塊的控制器,模型,視圖,放在一個(gè)文件內(nèi)管理,根據(jù)他們的父模塊不同,來(lái)進(jìn)行分別建立。(父模塊作為建立文件夾的標(biāo)準(zhǔn))
var MVC = {} //模型模塊 // get 得到模型 // add 添加模型 MVC.Model = (function () { //用來(lái)存儲(chǔ)數(shù)據(jù)層面的數(shù)據(jù) var M = {}; return { //讀取數(shù)據(jù)的方法 //@param {String} strName 讀取數(shù)據(jù)的名稱 //eg: get("a.b.c") => M.a.b.c "get": function ( strName ) { var path = strName.split("."); var reslut = M; for ( var i=0; i
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/79655.html
摘要:深入之繼承的多種方式和優(yōu)缺點(diǎn)深入系列第十五篇,講解各種繼承方式和優(yōu)缺點(diǎn)。對(duì)于解釋型語(yǔ)言例如來(lái)說(shuō),通過(guò)詞法分析語(yǔ)法分析語(yǔ)法樹,就可以開始解釋執(zhí)行了。 JavaScript深入之繼承的多種方式和優(yōu)缺點(diǎn) JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 寫在前面 本文講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 但是注意: 這篇文章更像是筆記,哎,再讓我...
摘要:在中,并沒(méi)有對(duì)抽象類和接口的支持。例如,當(dāng)對(duì)象需要對(duì)象的能力時(shí),可以有選擇地把對(duì)象的構(gòu)造器的原型指向?qū)ο?,從而達(dá)到繼承的效果。本節(jié)內(nèi)容為設(shè)計(jì)模式與開發(fā)實(shí)踐第一章筆記。 動(dòng)態(tài)類型語(yǔ)言 編程語(yǔ)言按數(shù)據(jù)類型大體可以分為兩類:靜態(tài)類型語(yǔ)言與動(dòng)態(tài)類型語(yǔ)言。 靜態(tài)類型語(yǔ)言在編譯時(shí)已確定變量類型,動(dòng)態(tài)類型語(yǔ)言的變量類型要到程序運(yùn)行時(shí),待變量被賦值后,才具有某種類型。 而JavaScript是一門典型...
摘要:首先,需要來(lái)理清一些基礎(chǔ)的計(jì)算機(jī)編程概念編程哲學(xué)與設(shè)計(jì)模式計(jì)算機(jī)編程理念源自于對(duì)現(xiàn)實(shí)抽象的哲學(xué)思考,面向?qū)ο缶幊淌瞧湟环N思維方式,與它并駕齊驅(qū)的是另外兩種思路過(guò)程式和函數(shù)式編程。 JavaScript 中的原型機(jī)制一直以來(lái)都被眾多開發(fā)者(包括本人)低估甚至忽視了,這是因?yàn)榻^大多數(shù)人沒(méi)有想要深刻理解這個(gè)機(jī)制的內(nèi)涵,以及越來(lái)越多的開發(fā)者缺乏計(jì)算機(jī)編程相關(guān)的基礎(chǔ)知識(shí)。對(duì)于這樣的開發(fā)者來(lái)說(shuō) J...
摘要:如下所示在規(guī)范中,已經(jīng)正式把屬性添加到規(guī)范中也可以通過(guò)設(shè)置和獲取對(duì)象的原型對(duì)象對(duì)象之間的關(guān)系可以用下圖來(lái)表示但規(guī)范主要介紹了如何利用構(gòu)造函數(shù)去構(gòu)建原型關(guān)系。 前言 在軟件工程中,代碼重用的模式極為重要,因?yàn)樗麄兛梢燥@著地減少軟件開發(fā)的成本。在那些主流的基于類的語(yǔ)言(比如Java,C++)中都是通過(guò)繼承(extend)來(lái)實(shí)現(xiàn)代碼復(fù)用,同時(shí)類繼承引入了一套類型規(guī)范。而JavaScript是...
摘要:設(shè)計(jì)模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時(shí)候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計(jì)模式必須要先搞懂面向?qū)ο缶幊?,否則只會(huì)讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識(shí)只有分享才有存在的意義。 是時(shí)候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...
摘要:對(duì)象會(huì)記住它的原型給對(duì)象提供了一個(gè)名為的隱藏屬性,某個(gè)對(duì)象的屬性默認(rèn)會(huì)指向它的構(gòu)造器的原型對(duì)象,即。我們通過(guò)代碼來(lái)驗(yàn)證再來(lái)實(shí)際上,就是對(duì)象跟對(duì)象構(gòu)造器的原型聯(lián)系起來(lái)的紐帶切記這句話,對(duì)未來(lái)理解原型鏈很有幫助。 封裝 封裝數(shù)據(jù) 在許多語(yǔ)言的對(duì)象系統(tǒng)中,封裝數(shù)據(jù)是由語(yǔ)法解析來(lái)實(shí)現(xiàn)的,這些語(yǔ)言也許提供了 private、public、protected 等關(guān)鍵字來(lái)提供不同的訪問(wèn)權(quán)限。例如:j...
閱讀 1368·2021-11-24 09:39
閱讀 1358·2021-11-04 16:12
閱讀 2701·2021-09-24 09:47
閱讀 3346·2021-09-01 10:50
閱讀 1487·2019-08-30 15:55
閱讀 1432·2019-08-30 15:43
閱讀 652·2019-08-30 11:08
閱讀 3588·2019-08-23 18:33