Javascript对象的创建模式 -- 深入了解Javascript

/*
    一、模式1:命名空间(namespace)
    优点:减少全局命名所需的数量,避免命名冲突或过度
*/
// 更简洁的方式
var MYAPP = MYAPP || {};

//定义通用方法
MYAPP.namespace = function (ns_string) {
    var parts = ns_string.split('.'),
        parent = MYAPP,
        i;

    // 默认如果第一个节点是MYAPP的话,就忽略掉,比如MYAPP.ModuleA
    if (parts[0] === "MYAPP") {
        parts = parts.slice(1);
    }

    for (i = 0; i < parts.length; i += 1) {
        // 如果属性不存在,就创建
        if (typeof parent[parts[i]] === "undefined") {
            parent[parts[i]] = {};
        }
        parent = parent[parts[i]];
    }
    return parent;
};
/*
    二、模式2:定义依赖
*/
var myFunction = function () {
    // 依赖模块
    var event = YAHOO.util.Event,
        dom = YAHOO.util.dom;

    // 其它函数后面的代码里使用局部变量event和dom
};
/*
    三、模式3:私有属性和私有方法 --通过闭包来实现
*/
function Gadget() {
    var name = "123";//私有属性
    //公有函数
    this.getName = function () {
        return name;
    }
}
var myObj; // 通过自执行函数给myobj赋值
(function () {
    var name = "123";//自由对象
    myObj = {
        //授权方法
        getName: function () {
            return name;
        }
    }
}());
/*
    四、模式4:Revelation模式  --隐藏私有方法的模式
    在外部先声明一个变量,然后在内部给变量赋值公有方法
*/
var myarray;
(function () {
    function isFunc() {

    }
    //通过赋值的方式,将上面所有的细节都隐藏了
    myarray = {
        myFunc: isFunc
    };
}());
/*
    五、模式5:链模式
    链模式可以你连续可以调用一个对象的方法,比如obj.add(1).remove(2).delete(4).add(2)这样的形式,其实现思路非常简单,就是将this原样返回
*/
var obj = {
    value: 1,
    increment: function () {
        return this;
    },
    add: function () {
        return this;
    }
}
obj.increment().add();
/*
    六、模式6:函数语法糖
    函数语法糖是为一个对象快速添加方法(函数)的扩展,这个主要是利用prototype的特性
*/
if (typeof Function.prototype.method !== "function") {
    Function.prototype.method = function (name, implementation) {
        this.prototype[name] = implementation;
        return this;
    };
}
var Person = function (name) {
    this.name = name;
}
.method('getName',
            function () {
                return this.name;
            })
.method('setName', function (name) {
    this.name = name;
    return this;
});
/*
    六、模式7:对象常量
    对象常量是在一个对象提供set,get,ifDefined各种方法的体现,而且对于set的方法只会保留最先设置的对象,后期再设置都是无效的,已达到别人无法重载的目的
*/
var constant = (function () {
    var ownProp = Object.prototype.hasOwnProperty,
        // 只允许设置这三种类型的值
        allowed = {
            string: 1,
            number: 1,
            boolean: 1
        },
        consstants = {};
    return {
        set: function (name, value) {
            if (this.isDefined(name)) {
                return false;
            }
            if (!ownProp.call(allowed, typeof value)) {
                return false;
            }
            constants[name] = value;
            return true;
        },
        get: function () {
            return null;
        },
        isDefined: function (name) {
            return ownProp.call(constants, name);
        }
    }
}());
/*
    六、模式8:沙盒模式
    沙盒(Sandbox)模式即时为一个或多个模块提供单独的上下文环境,而不会影响其他模块的上下文环境,比如有个Sandbox里有3个方法event,dom,ajax,在调用其中2个组成一个环境的话,和调用三个组成的环境完全没有干扰
*/
function Sandbox() {
    var args = Array.prototype.slice.call(arguments), //获取函数参数
        callback = args.pop(),//最后一个参数,并从args除去
        modules = (args[0] && typeof args[0] === "string") ? args : args[0], //除去最后一个参数,都为要选择的模块
        i;

    //强制使用new修饰符
    if (!(this instanceof Sandbox)) {
        return new Sandbox(modules, callback);
    }
    // 向this对象上添加模块
    // 如果没有模块或传入的参数为 "*" ,则以为着传入所有模块
    if (!modules || modules == '*') {
        modules = [];
        for (i in Sandbox.modules) {
            if (Sandbox.modules.hasOwnProperty(i)) {
                modules.push(i);
            }
        }
    }

    // 初始化需要的模块
    for (i = 0; i < modules.length; i += 1) {
        Sandbox.modules[modules[i]](this);
    }

    // 调用 callback
    callback(this);
}
Sandbox.modules = {};

Sandbox.modules.dom = function (box) {
    box.getElement = function () {
    };
    box.getStyle = function () {
    };
    box.foo = "bar";
};

Sandbox.modules.event = function (box) {
    // access to the Sandbox prototype if needed:
    // box.constructor.prototype.m = "mmm";
    box.attachEvent = function () {
    };
    box.detachEvent = function () {
    };
};

Sandbox.modules.ajax = function (box) {
    box.makeRequest = function () {
    };
    box.getResponse = function () {
    };
};
// 调用方式
Sandbox(['ajax', 'event'], function (box) {
    console.log(typeof (box.foo));
    // 没有选择dom,所以box.foo不存在
});

Sandbox('ajax', 'dom', function (box) {
    console.log(typeof (box.attachEvent));
    // 没有选择event,所以event里定义的attachEvent也不存在
});

Sandbox('*', function (box) {
    console.log(box); // 上面定义的所有方法都可访问
});
/*
    六、模式9:静态成员
    静态成员(Static Members)只是一个函数或对象提供的静态属性,可分为私有的和公有的
*/
//  1. 公有静态函数
// 构造函数
    var Gadget = function () {
    };

    // 公有静态方法
    Gadget.isShiny = function () {
        return "you bet";
    };
    // 原型上添加的正常方法
    Gadget.prototype.setPrice = function (price) {
        this.price = price;
    };
    // 调用静态方法
    console.log(Gadget.isShiny()); // "you bet"

    // 创建实例,然后调用方法
    var iphone = new Gadget();
    iphone.setPrice(500);
    console.log(typeof Gadget.setPrice); // "undefined"
    console.log(typeof iphone.isShiny); // "undefined"
    Gadget.prototype.isShiny = Gadget.isShiny;
    console.log(iphone.isShiny()); // "you bet"
//  2. 私有静态函数 --利用闭包特性实现
//  a.第一种实现方式:
    var Gadget = (function () {
        // 静态变量/属性
        var counter = 0;

        // 闭包返回构造函数的新实现
        return function () {
            console.log(counter += 1);
        };
    }()); // 立即执行
    var g1 = new Gadget(); // logs 1
    var g2 = new Gadget(); // logs 2
    var g3 = new Gadget(); // logs 3
//  b.第二种方式:
    var Gadget = (function () {
        // 静态变量/属性
        var counter = 0,
            NewGadget;

        //新构造函数实现
        NewGadget = function () {
            counter += 1;
        };

        // 授权可以访问的方法
        NewGadget.prototype.getLastId = function () {
            return counter;
        };

        // 覆盖构造函数
        return NewGadget;
    }()); // 立即执行

    var iphone = new Gadget();
    iphone.getLastId(); // 1
    var ipod = new Gadget();
    ipod.getLastId(); // 2
    var ipad = new Gadget();
    ipad.getLastId(); // 3

 

posted @ 2015-07-28 19:26  RyanRuan  阅读(177)  评论(0编辑  收藏  举报
View Code