资讯专栏INFORMATION COLUMN

JavaScript_设计模式

BDEEFE / 350人阅读

摘要:设计模式是一套可复用的,被众人知晓,经过编目分明的,经验的总结。创建类安全工厂判断是否调用关键字设计模式设计模式运算符可以用来判断某个构造函数的属性所指向的對象是否存在于另外一个要检测对象的原型链上。

设计模式

是一套可复用的,被众人知晓,经过编目分明的,经验的总结。
作用:使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性

模式类型

创建型设计模式:解决对象在创建时产生的一系列问题。
结构型设计模式:解决类或对象之间组合时产生的一系列问题
行为型设计模式:解决类或对象之间的交互以及职责分配的一些列问题

23种设计模式

创建型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。 (5)
结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。(7)
行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。(11)

设计模式,框架,架构与库

设计模式:是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,它强调的是一个设计问题的解决方法

框架:软件框架是项目软件开发过程中提取特定领域软件的共性部分形成的体系结构,不同领域的软件项目有着不同的框架类型。框架不是现成可用的应用系统。而是一个半成品,提供了诸多服务,开发人员进行二次开发,实现具体功能的应用系统。 ( 只有基础公共代码,而没有业务逻辑的产品,就是框架。)

架构:简单的说架构就是一个蓝图,是一种设计方案,将客户的不同需求抽象成为抽象组件,并能够描述这些抽象组件之间的通信和调用,偏重于设计。框架比架构更具体,更偏重于技术

工具库:是类(方法)的集合,这些类之间可能是相互独立的。可以直接调用它,而不必再写一个。框架也往往是类(方法)的集合;但框架中的各个类并不是孤立的,而框架中的业务逻辑代码是将不同的类“连”在一起,在它们之间建立协作关系

设计模式研究的是针对单一问题的设计思路和解决方法,一个模式可应用于不同的框架和被不同的语言所实现;而框架则是一个应用的体系结构,是一种或多种设计模式和代码的混合体虽然它们有所不同,但却共同致力于使人们的设计可以被重用,在思想上存在着统一性的特点,因而设计模式的思想可以在框架设计中进行应用。

工厂模式 简单工厂

定义:用来创建一种类型的产品实例,所以他创建的对象单一

特点:

通过将创建过程寄生在工厂内,可以解决全局变量污染问题

创建的产品对象单一。

对工厂进行改造可以适应不同的需求。











批量生产

    
        
        
    
        
        
    
    
    
        
    

第一种:
在外部创建一个批量生产的工厂,然后再内部调用工厂,它的问题是需要另外创建一个工厂

第二种:
通过在工厂方法内部进行分支判断,决定创建单个产品或者品量单品。
这种方式在工厂内部调用该厂,依赖了工厂名称。

第三种:
通过在工厂方法内部进行分支判断,决定创建单个产品或者品量单品。
这种方式在工厂内部调用了,arguments.callee解决了对工厂名称的依赖。

寄生增强工厂

通过对寄生在工厂内部的对象增添方法属性,使在不改变原类的基础上,完成对类的拓展

在工厂内部实例化类 这一步叫做寄生

对实例化的类拓展方法和属性 这一步叫做增强

将这个对象返回。 这一步是工厂。







  
安全工厂模式

又叫:安全类

特点,不论在调用的时候有没有new关键字,得到的结果都是一样的。

判断this是否是只想当前对象的。通过instanceof

如果是通过new关键字创建的,就直接对this赋值

如果不是,主动创建,并返回该实例。

//创建 Book类
//安全工厂
var Book = function ( title ) {
    
    //判断是否调用 new 关键字
    if ( this instanceof Book ) {
        
        this.title = title;
        
    } else {
        
        return new Book(title);    
        
    }
    
}

//var b1 = new Book("设计模式1");
var b2 = Book("设计模式2");

//console.log( b1 ,b1 instanceof Book );  //true
console.log( b2 ,b2 instanceof Book ); //true

instanceof运算符可以用来判断某个构造函数的prototype属性所指向的對象是否存在于另外一个要检测对象的原型链上。

工厂方法

通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例
特点:

创建多类对象

也是对类的再封装

步骤:

声明参数
循环创建类
对类的添加方法
将实例化对象返回


    
    





原型模式

通过将对象的原型指向类的原型实现对该对象原型的属性与方法的共享。

var Rect = function( x,y ){
    
    //继承
    Base.apply(this,arguments);
    this.dom.className = "rect";

}

Rect.prototype = new Base();

原型模式一种创建型设计模式
它基于javascript原型链原理实现的
是一种组合式继承
对于处理复杂的类,通过提取公共部分实现对类优化

单例模式 简单单体模式

只能创建一个实例, 把所有代码和数据组织到一个地方. 全局的资源,公共的数据, 组织到一起.统一的管理.
单体模式 一般不采用new 关键字. 已经存在了对象.
主要用来 划分命名空间(区分代码,降低耦合性)

var Singleton={
    attr1: true,
    attr2: 10,
    method1: function(){
        alert(this.attr1);
    },
    method2: function(){
        alert("方法2");
    }
}
惰性单例

借用闭包创建单体 闭包主要的目的:就是保护数据,不受外界所干扰.
通过闭包将我们的single封装起来,避免外部访问而实例化,这样可保证实例化一次,闭包的返回函数的作用域在闭包里面,所以可以访问到single类对其实例化,这样在执行LazySingle才会对single类实例化

特点:
只能被实例化一次
推迟了实例化时间

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();
分支单体

判读程序的分支 --> 浏览器差异检测

var Slington = (function(){
    
    var def = true;

    var More = function(){

        var objA = { //火狐浏览器  内部的一些配置
            attr1: "ff attr1",
            //属性1
            //方法1
        }
        var objB = {  //ie浏览器 内部的一些配置
            attr2: "ie attr1",
            //属性1
            //方法1
        }

    }
    return (def) ? new More().objA : new More().objB;

})();
适配器模式

将一个类(对象)的接口(属性或者方法)转化成另一个类(对象)的接口,以满足用户的需要,使类(对象)之间接口的不兼容问题得以解决。

对被适配的数据的一个分解再封装的一个过程。
这个过程中会造成一定的开销。但远比更改原有业务逻辑成本低。

请求数据适配

需要dataAdaptor函数中有适配映射表

 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 ) {
        
        //把第三方数据源中的数据,放到自己数据中的数组中的相应位置
        //map[i] -> 自己数据源中的位置
        //i -> 第三方数据源中的属性
        
        arr[map[i]] = data[i];
        
    }
    
    //匹配出来后的数据
//                arr[0] = data.href
//                arr[1] = data.src
//                arr[2] = data.title
    
    return arr;
    
}


//第三方提供数据
//           obj.href  : 链接地址    
//                obj.src   : 图片地址
//                obj.title : 图片标题

$.get("xxx.json",function ( oD ) {
    
    if ( oD && oD.errno === 0 ) {
        
        var newRes = new DataAdaptor( oD.data ); 
        
        DealData(newRes);
        
    }
    
})
参数适配

使用继承
使用 || 运算符

function extend ( targetObj,obj ) {
                
    for ( var i in obj ) {
        
        targetObj[i] = obj[i];
        
    }
    
    return targetObj;
    
}

var Button = function ( param ) {
    
    var btn = document.createElement("button");
    
    //默认参数
    var def = {
        "background": "tan",
        "color": "yellow",
        "fontSize": "12px",
        "text": "按钮"
    }
    
    // 适配用户传递的参数与默认的参数
    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"});
组合模式

部分整体模式,将对象表示成树形结构,表示部分整体关系。所以部分与整体的行为习惯达到一致型。

组合模式中只有两种类型对象,组合对象,叶子对象

创建类的步骤:

构造函数

构造函数继承

保留参数

初始化数据

原型式继承,继承基类方法
重写init方法
添加其他方法

它是将整体分解成为一个个部分,再有部分重新拼装成一个整体。部分分解的也多,整合结果也就越多。
它的部分与整体之间具有行为的一致性。
部分拼装成整体的过程具有多样性

观察者模式

叫消息系统,消息机制,或者发布订阅模式。通过消息系统实现对象或者类之间的解耦。
解决是一种依赖关系,
解决了,主体与观察者之间的一种依赖关系。
被观察者对象或者类也可以是观察者,观察者也可以是被观察者
观察者内部变化不会影响到被观察者,反过来一样

var Observer = (function () {

var __msg = {};

return {
    
    //添加订阅者 
    //@param {String} type  订阅者名字
    //@param {Function} fn  执行函数  
    
    add: function ( type,fn ) {
        
        if ( __msg[type] ) {
            
            __msg[type].push(fn);
            
        }    else {
            
            __msg[type] = [fn];
            
        }
        
        return this;
        
    },

     //执行回调函数
     //@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;
        
    },
     // 移除回调函数
     // @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;
    }
    
}

})()
策略模式

封装一组算法,使其可以互相替换,这组算法本身具有独立性,不受客户端影响。

特点:

它是行为型模式

每种都是独立的,所他们之间可以相互替换

他解决是使用者与策略算法之间的耦合

算是是独立的方便我们进行单测

算法在使用时候的过程是不一样的,但结果是一样的

tween中使用的是策略模式,价格算法,表单验证.



价格:

淘宝价:

//表单验证

var InputStrategy = (function () {
            
//策略模型
var strategy = {
    
    //判断是否为空
    "notNull": function ( val ) {
        
        return /^s*$/g.test(val) ? "输入的内容不能为空" : "";
        
    },
    
    //判断是否是数字
    "isNumber": function ( val ) {
        
        return /^-?[d]+(.[d])?$/.test(val) ? "" : "输入的不是一个正确的数字";
        
    },
    
    //判断电话格式  010-12345678 1234-1234567
    "isTelephoneNumber": function ( val ) {
        
        return /^[d]{3}-[d]{8}$|^[d]{4}-[d]{7}$ /.test(val) ? "" : "请输入一个正确的电话号码";
        
    }
    
}

return {
    //检测表单输入的文本内容是否正确
    //@param {String} val 检测文本
    //@param {String} type 检测算法
    
    check: function ( val,type ) {
        
        if ( strategy[type] ) {
            
            return strategy[type](val);
            
        } else {
            
            return "没有该算法";
            
        }
        
    }
}

})()


//策略名称 与 页面中的表单的 映射表
var arr = ["notNull", "isNumber", "isTelephoneNumber"];

for ( var i=1; i<4; i++ ) {

checkInp( "inp"+i ,"err"+i,arr[i-1] );

}

//执行 检测表单
function checkInp ( inpId,errId,type ) {

//添加监听
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 = "";
        
    }
    
}

}
命令模式

将请求与实现解耦并封装,实现请求对客户端实现参数化。

命令模式渲染视图

页面中有好多数据源,要对这些数据源渲染页面,传统方式,渲染页面时候,将视图,数据,业务耦合在一起了,不利于开发,所以要将这些实现东西提取出来封装成一个个命令供使用,来实现代码复用,并简化的创建操作


        

命令模式解决了命令的发起者与命令的实现者之间的耦合
命令的发起者(调用命令的时候) 不必去了解命令是如何实现的以及命令是如何运行的。
所有的在使用具有一致性。
命令模式在一定程度上简化了操作。

canvas绘图

canvas绘图的 上下文 ctx 一些问题

模块外界访问不到 ctx
ctx很重要,不论操作都需要使用这个变量
一旦更改这个变量,会造成很严重的后果,造成原有功能失效。

把ctx封装成内部方法。 封装成 cmd 对象下的方法, 在excute 命令执行方法中匹配 cmd 中的方法







迭代器模式 数组迭代器
// 遍历
// arr 遍历的函数
// cb
function each ( arr,cb ) {
    
    for ( var i=0,len=arr.length; i
对象迭代器
//obj 要被遍历的对象
//cb 遍历回调函数
function each( obj,cb ){
    for( var i in obj ){
        cb && cb.call(obj,obj[i],i);
    }
}
function each (obj, fn) {
    // obj是一个数组时候
    if (obj instanceof Array) {  //判断是否是数组
        //迭代数组
        for (var i = 0, len = obj.length; i < len; i++) {
            fn(obj[i], i, obj)
        }
    // obj是一个对象
    } else { 
        // 迭代对象
        for (var i in obj) {
            fn(obj[i], i, obj)
        }
    }
}
面向对象中的迭代器

面向对象中有时需要遍历实例化对象中的自身属性,过滤掉原型上的属性,可以通过 hasOwnPrototy 来实现

// 遍历实例化对象自身的属性,过滤掉原型上的属性
// obj    实例化对象
// cb     回调函数

function  each ( obj,cb ) {
    for ( var i in obj ) {
        if ( obj.hasOwnPrototy(i) ) {
            cb && cb.call(obj,obj[i],i);
        }
    }
}

迭代器的特点

本身并没有删除循环语句,只是将循环语句转移到迭代器的内部,

迭代器模式中,数据对象内部的结构,只需要关注处理函数。

移出了循环语句,使得代码看着更清晰

迭代器模式是将数据源于处理函数之间的解耦

DOM迭代器

        
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
委托模式

是将多个对象接收并处理的请求,统一委托给另外一个对象处理

委托模式解决事件数量问题

解决事件绑定数量的问题,为一堆元素绑定事件,通过for循环遍历绑定,无形中绑定了n个事件,这样在内存中造成一定的开销。
可以通过这些元素公共的父元素,对其绑定事件,通过e.target事件触发的目标元素的某些属性来确认是哪些元素需要绑定事件来解决上面的问题。
通常可以判断元素的名称类名id,及其属性
通过对子元素的某些特性判断,来实现对该元素的事件的绑定。

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);
未来元素事件绑定问题

传统式方式通过for循环,只能对现用元素进行事件绑定,当需要在后面添加新的元素的时候,该方案不能对新元素绑定事件。
委托模式,通过将子元素的事件绑定委托给父元素,事件对子元素事件绑定的效果,这样,在父元素中添加新的子元素,同样可以获取绑定事件的效果

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中给我提供了一个专用来是做事件委托事件绑定方法,delegate,它实质上是通过on方法实现的


内存外泄

在低版本IE浏览器中,内存只会清理哪些没有被javascript引用的dom元素,所以在对元素定义事件时候,如果将元素清理一定要将该元素绑定的事件解除,因此要在事件内部显性清除事件绑定,但这就要写在原有事件内部,

var oDiv = document.getElementsByTagName("div")[0];
            
var oBtn = document.getElementsByTagName("button")[0];

oBtn.onclick = function () {
    
    oBtn.onclick = null;  //手动清除事件绑定
    oDiv.innerHTML = "info";
    
}

更好的解决方案是对该元素的父元素委托绑定事件,这样当清理该元素时候,由于没有事件的绑定,该元素即会被清理

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";
        
    }
    
}    
数据分发

动态页面中,页面中的每个模块会对应一个数据请求,然而如果页面中的这类模块很多,就要发送多个请求,但是并发请求的个数是有限的 ,因此后面的请求就会被堵塞,为了解决这类问题,可以将这些请求委托给父请求统一处理,当接收数据后,解析数据,并派发给各个子模块中,供其使用

//对每个模块进行封装
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]);
        
    }
    
}

//发出 get 请求
$.get("data/all.json",function ( res ) {
    
    if ( res.errno === 0 ) {
        
        Deal( res.data );
        
    }
    
});
节流模式

对重复的业务逻辑进行节流控制,执行最后一次操作并取消其他操作,以提高性能。

特点:

通过计时器延迟程序的执行

通过计时器,使程序异步执行,避免开销大的程序造成的堵塞

条件:

程序可控:即取消后是否可以继续执行

异步执行:即程序是否可以异步执行

节流器

通过jQuery的stop方法禁止动画的排队,但是对于滚动这种高频事件,每次执行都会添加动画
通过节流模式,短时间内触发多次动画时,前面动画被取消添加,这样只执行最后一次,来提高性能

节流器通常提供两种使用方式
触发操作
清除操作

//对重复的业务逻辑,通常执行最后一个,取消前面的业务逻辑,来实现业务逻辑的优化。
//高频事件, mousemove ,window.onscorll
var Throttle = function () {


    var isClear = arguments[0] , fn;

    if ( isClear !== "true" ) {

     // 触发操作
     // @param[0] [Function]  表示函数的名称
     // @param[1] [Object] 配置项

        //触发操作
        fn = isClear;
        var o = arguments[1] || {};

        var obj = {
            time: o.time || 200,
            context: o.context || null,
            data: o.data || null
        };  //配置项
        
        //设表先关
        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] 取消的函数名称

        //取消操作
        fn = arguments[1];

        //清除定时器
        fn._throttle && clearTimeout(fn._throttle);

    }

}

function goBack(){
    console.log(1);
}

//触发
Throttle(goBack,{time: 500,data: {msg: "hello"}});

//清除操作
// Throttle(true,goBack);

统计节流

统计是什么,为什么要做统计?
统计是为了了解用户对页面使用习惯或者使用方式的,要为页面添加统计来帮助分析用户的使用行为

统计的实现
当用户触发一次交互的时候,想向服务器端发送一条信息,将其记录下来,保存在服务器中。
前端的一些交互,有时候是不需要向服务器端发送请求的,此时,服务器端是不知道这些行为的,所以要向服务器端发送请求告知

统计请求方面的考虑
post请求要比get请求发送的时处理事情要多,在做统计的时候就不考虑post请求
Ajax可以发送get请求,但是要写好多逻辑代码
请求文档是一个get请求,但是请求过来的页面中的信息量比较多
script标签也是get请求,
link标签也是一个get请求
img标签也是get请求
相比较这几种,img的发送成本更低一些,在发送统计请求的时候,用img(0字节的图片作为中转发送get请求)的get请求

请求节流
页面中的一些高频事件,做统计的时候,会不停的发送统计,由于请求的并发次数是有限的 ,不能同时发送这么多的请求。这回造成后面资源的加载延迟,要对这些统计做节流处理

var img = new Image();
            
function sendLog ( val ) {
    
    var reslutStr = "";
    for ( var i in val ) {
        
        reslutStr += "&" + i + "=" +  val[i];
        
    }
    
    img.src = "a.jpg?" + reslutStr;
    
}

统计的拼接

一条统计 ?Type=click&date=123
将两条统计拼接在一起 ?Type=click&dat2=123&type=mouseover&date=234,这样的化出现相同的字段了,不能这么拼接,
可以将一条统计作为一个值: ?Log1=typeclick|date123 //将一条数据,作为请求的 一个 id.
拼接两个统计的时候,就可以?Log1=typeclick|date123&log2=typemouserover|date234

//节流处理: 当发送第一个请求的时候,将其缓存下来,当其触发的次数达到规定的次数再发送
//想缓存,需要有缓存容器, dataCache   次数,需要有次数的规定。maxNum
//将一条数据,作为请求的  一个  id.

var LogPack = (function () {
    
    var dataCache = [];  //缓存容器
    
    var maxNum = 10; //缓存的次数                
    
    var oImg = new Image();  //请求的触发器

    var itemSplit = "|";
    var keyValSplit = "*";
    
    //发送统计
    function sendLog () {
        
        var logs = dataCache.splice(0,10);
        
        var str = "";
        
        for ( var i=0; i maxNum ) {
            
            //发送
            sendLog();
            
        }
        
    };
    
})()

//触发
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()
    });
    
}

//发送结果

MVC 后端的MVC概念

Model(模型)表示应用程序核心(比如数据库记录列表)。
是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。

View(视图)显示数据(数据库记录)。
是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的

Controller(控制器)处理输入(写入数据库记录)
是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

前端中的实践

Model,页面数据的存储操作
View,渲染出可视(给人看)的页面操作
Controller,页面的交互对视图的更改以及对数据的更改

View层通过Model渲染数据,所以View层可以访问Model层
Controller层可以对Model写入读取数据,所以Controller可以访问Model层
Controller层可以对View层打开弹层,浮层等交互,所以Controller可以访问View层

在前端的框架中,很多框架是基于MVC模式实现,比如BackBone
它将MVC进行了一些改造,比如它允许Model层可以访问View层,实现数据层的更新通知View层视图的渲染

通常一个模块对应一个控制器,一个模型,一个视图,那么如果将页面所有模块中的视图,控制器模型放在一起,逻辑比较混乱,为了管理方便,将一个模块的控制器,模型,视图,放在一个文件内管理,根据他们的父模块不同,来进行分别建立。(父模块作为建立文件夹的标准)

var MVC = {}

//模型模块
// get 得到模型
// add 添加模型
MVC.Model = (function () { 
    
    //用来存储数据层面的数据
    var M = {};
    
    return {
         //读取数据的方法
         //@param {String} strName 读取数据的名称
         //eg: get("a.b.c") => M.a.b.c
        "get": function ( strName ) {
            
            var path = strName.split(".");
            
            var reslut = M;
            
            for ( var i=0; i           
               
                                           
                       
                 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79655.html

相关文章

  • 深入理解JavaScript

    摘要:深入之继承的多种方式和优缺点深入系列第十五篇,讲解各种继承方式和优缺点。对于解释型语言例如来说,通过词法分析语法分析语法树,就可以开始解释执行了。 JavaScript深入之继承的多种方式和优缺点 JavaScript深入系列第十五篇,讲解JavaScript各种继承方式和优缺点。 写在前面 本文讲解JavaScript各种继承方式和优缺点。 但是注意: 这篇文章更像是笔记,哎,再让我...

    myeveryheart 评论0 收藏0
  • JavaScript设计模式与开发实践 | 01 - 面向对象的JavaScript

    摘要:在中,并没有对抽象类和接口的支持。例如,当对象需要对象的能力时,可以有选择地把对象的构造器的原型指向对象,从而达到继承的效果。本节内容为设计模式与开发实践第一章笔记。 动态类型语言 编程语言按数据类型大体可以分为两类:静态类型语言与动态类型语言。 静态类型语言在编译时已确定变量类型,动态类型语言的变量类型要到程序运行时,待变量被赋值后,才具有某种类型。 而JavaScript是一门典型...

    suxier 评论0 收藏0
  • 理解JavaScript的核心知识点:原型

    摘要:首先,需要来理清一些基础的计算机编程概念编程哲学与设计模式计算机编程理念源自于对现实抽象的哲学思考,面向对象编程是其一种思维方式,与它并驾齐驱的是另外两种思路过程式和函数式编程。 JavaScript 中的原型机制一直以来都被众多开发者(包括本人)低估甚至忽视了,这是因为绝大多数人没有想要深刻理解这个机制的内涵,以及越来越多的开发者缺乏计算机编程相关的基础知识。对于这样的开发者来说 J...

    iKcamp 评论0 收藏0
  • 深入理解Javascript原型关系

    摘要:如下所示在规范中,已经正式把属性添加到规范中也可以通过设置和获取对象的原型对象对象之间的关系可以用下图来表示但规范主要介绍了如何利用构造函数去构建原型关系。 前言 在软件工程中,代码重用的模式极为重要,因为他们可以显著地减少软件开发的成本。在那些主流的基于类的语言(比如Java,C++)中都是通过继承(extend)来实现代码复用,同时类继承引入了一套类型规范。而JavaScript是...

    ethernet 评论0 收藏0
  • JS程序

    摘要:设计模式是以面向对象编程为基础的,的面向对象编程和传统的的面向对象编程有些差别,这让我一开始接触的时候感到十分痛苦,但是这只能靠自己慢慢积累慢慢思考。想继续了解设计模式必须要先搞懂面向对象编程,否则只会让你自己更痛苦。 JavaScript 中的构造函数 学习总结。知识只有分享才有存在的意义。 是时候替换你的 for 循环大法了~ 《小分享》JavaScript中数组的那些迭代方法~ ...

    melody_lql 评论0 收藏0
  • javascript设计模式与开发实践(二)- 封装和原型模式

    摘要:对象会记住它的原型给对象提供了一个名为的隐藏属性,某个对象的属性默认会指向它的构造器的原型对象,即。我们通过代码来验证再来实际上,就是对象跟对象构造器的原型联系起来的纽带切记这句话,对未来理解原型链很有帮助。 封装 封装数据 在许多语言的对象系统中,封装数据是由语法解析来实现的,这些语言也许提供了 private、public、protected 等关键字来提供不同的访问权限。例如:j...

    luxixing 评论0 收藏0

发表评论

0条评论

BDEEFE

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<