prototype与面向对象取舍

使用prototype原型继承和使用面向对象,都可以实现闭包的效果。那么这两个的选择点,就是方法会不会产生多个实例

例如,我们需要做一个闭包数组,并给他提供一个添加方法。

这两种写法都可以实现闭包,但是面向对象的写法,只能存在一个。我们无法对他进行初始化,而原型继承写法,我们则可以对他进行初始化操作。

所以,当我们这个方法,在整个程序中,是唯一的存在。我们可以使用面向对象的写法,如果可以存在多个,则使用prototype这种写法。

!(function () {
    //原型继承写法
    var Validator = function(){
        this.cache = [];
    };
    Validator.prototype.add = function(item){
        this.cache.push(item);
    };
    var validator = new Validator(),validatorr = new Validator();
    validator.add("test1"); console.log(validator.cache);
    validatorr.add("test2"); console.log(validatorr.cache);
    //面向对象写法
    var Validator2 = {
        cache : [],
        add : function(item){
            this.cache.push(item);
        }
    };
    Validator2.add("test3"); console.log(Validator2.cache);
    Validator2.add("test4"); console.log(Validator2.cache);
})()

调用父类构造函数

继承关系的两个对象,在实例的过程中,可以通过修改指向,来调整调用构造函数

!(function () {
    var A = function (light) {
        this.light1 = light;
    };
    var B = function (light) {
        this.light = light;
        A.apply(this,arguments);//你需要手动调用A的构造方法
    };
    //给B赋值的同时,给A赋值
    B.prototype = new A();
    var C = new B(123);
    console.log(C.light);
    console.log(C.light1);
})()

单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。例如:线程池,全局缓存,登录浮窗。

首先我们需要把单例的逻辑代码单独提取,然后使用惰性单例的方式,也就是返回方法。只有在点击的时候,才会进行执行。

javascript的单例,跟类不一样。无需创建多余的构造函数这些,直接创建全局变量即可。

!(function () {
    //管理单例的逻辑代码,如果没有数据则创建,有数据则返回
   var getSingle = function(fn){ //参数为创建对象的方法
       var result;
       return function(){ //判断是Null或赋值
           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';
    };
})()

单例模式
View Code

策略模式

定义一系列的算法,把它们一个一个封装起来。将算法的使用与算法的实现分离开来。

javascript的策略模式很简单,把算法直接定义成函数即可。

策略模式的优点与缺点

  1. 有效的避免许多重复的复制粘贴作业。
  2. 开闭原则的完美支持,算法完全独立易于切换、理解、拓展。
  3. 算法复用性强
  4. 使用组合和委托让Validator类拥有执行算法的能力,也是继承的一种轻便替代方式

缺点

  1. 会增加许多策略类或策略对象。
  2. 违反迪米特法则,会将strategy暴露给客户所有实现。
!(function () {
    //定义算法方法
    var strategies = {
        "S":function(salary){
          return salary * 4;
        },
        "A":function(salary){
            return salary * 3;
        },
        "B":function(salary){
            return salary * 2;
        }
    };
    //执行算法
    var calculateBouns = function(level,salary){
      return strategies[level](salary);
    };
    console.log(calculateBouns('S',2000));
})() 
View Code

undefined终止循环

(写具体代码之前,先记录一个知识点)。当循环表达式为undefined时,循环会终止

!(function(){
    var cale = [1,2,3];
    for(var i= 0,validate;validate=cale[i];)
    {
        cale.shift();
        console.log(validate);
    }
})() //1,2,3
View Code

观察者模式

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。

例如事件绑定,就是一个标准的观察者模式

document.body.addEventListener('click',function(){
       console.log(2);
    },false);
    document.body.click();
View Code

命令模式

命令模式指的是一个执行某些特定事情的指令。常见的应用场景是:有时候需要向对象发送请求,但不知道接受者是谁,也不知道请求的操作是什么。

例如:订餐,客人需要给厨师发送请求,至于那个厨师做,做的步骤。客人不知道。这就是命令模式。

//定义命令模式执行
    var setCommand = function (button, func) {
        button.onclick = function () {
            func.execute();
        };
    };
    var MenuBar = {
        refresh: function () {
            console.log("刷新页面");
        }
    };
    var RefreshMenuBarCommand = function (receiver) {
        return {
            execute: function () {
                receiver.refresh();
            }
        }
    };
    var refreshMenuBarCommand = RefreshMenuBarCommand("MenuBar");
    setCommand(button1,refreshMenuBarCommand);
View Code

·························有待补充