成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript_設(shè)計(jì)模式

BDEEFE / 510人閱讀

摘要:設(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)題

23種設(shè)計(jì)模式

創(chuàng)建型模式:?jiǎn)卫J?、抽象工廠模式、建造者模式、工廠模式、原型模式。 (5)
結(jié)構(gòu)型模式:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。(7)
行為型模式:模版方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式(Interpreter模式)、狀態(tài)模式、策略模式、職責(zé)鏈模式(責(zé)任鏈模式)、訪問(wèn)者模式。(11)

設(shè)計(jì)模式,框架,架構(gòu)與庫(kù)

設(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ì)工廠名稱的依賴。

寄生增強(qiáng)工廠

通過(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)化

單例模式 簡(jiǎn)單單體模式

只能創(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ù)邏輯成本低。

請(qǐng)求數(shù)據(jù)適配

需要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繪圖

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; i maxNum ) {
            
            //發(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é)果

MVC 后端的MVC概念

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ù)。

前端中的實(shí)踐

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

相關(guān)文章

  • 深入理解JavaScript

    摘要:深入之繼承的多種方式和優(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)。 但是注意: 這篇文章更像是筆記,哎,再讓我...

    myeveryheart 評(píng)論0 收藏0
  • JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐 | 01 - 面向?qū)ο蟮?em>JavaScript

    摘要:在中,并沒(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是一門典型...

    suxier 評(píng)論0 收藏0
  • 理解JavaScript的核心知識(shí)點(diǎn):原型

    摘要:首先,需要來(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...

    iKcamp 評(píng)論0 收藏0
  • 深入理解Javascript原型關(guān)系

    摘要:如下所示在規(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是...

    ethernet 評(píng)論0 收藏0
  • JS程序

    摘要:設(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ù)組的那些迭代方法~ ...

    melody_lql 評(píng)論0 收藏0
  • javascript設(shè)計(jì)模式與開發(fā)實(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...

    luxixing 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<