深入理解JavaScript系列(47):对象创建模式(上篇)


Posted in Javascript onMarch 04, 2015

介绍

本篇主要是介绍创建对象方面的模式,利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码。

模式1:命名空间(namespace)

命名空间可以减少全局命名所需的数量,避免命名冲突或过度。一般我们在进行对象层级定义的时候,经常是这样的:

var app = app || {};

app.moduleA = app.moduleA || {};

app.moduleA.subModule = app.moduleA.subModule || {};

app.moduleA.subModule.MethodA = function () {

    console.log("print A");

};

app.moduleA.subModule.MethodB = function () {

    console.log("print B");

};

如果层级很多的话,那就要一直这样继续下去,很是混乱。namespace模式就是为了解决这个问题而存在的,我们看代码:
// 不安全,可能会覆盖已有的MYAPP对象

var MYAPP = {};

// 还好

if (typeof MYAPP === "undefined") {

    var MYAPP = {};

}

// 更简洁的方式

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;

};

调用代码,非常简单:
// 通过namespace以后,可以将返回值赋给一个局部变量

var module2 = MYAPP.namespace('MYAPP.modules.module2');

console.log(module2 === MYAPP.modules.module2); // true
// 跳过MYAPP

MYAPP.namespace('modules.module51');
// 非常长的名字

MYAPP.namespace('once.upon.a.time.there.was.this.long.nested.property');

模式2:定义依赖

有时候你的一个模块或者函数可能要引用第三方的一些模块或者工具,这时候最好将这些依赖模块在刚开始的时候就定义好,以便以后可以很方便地替换掉。

var myFunction = function () {

    // 依赖模块

    var event = YAHOO.util.Event,

        dom = YAHOO.util.dom;
    // 其它函数后面的代码里使用局部变量event和dom

};

模式3:私有属性和私有方法

JavaScript本书不提供特定的语法来支持私有属性和私有方法,但是我们可以通过闭包来实现,代码如下:

function Gadget() {

    // 私有对象

    var name = 'iPod';

    // 公有函数

    this.getName = function () {

        return name;

    };

}

var toy = new Gadget();
// name未定义,是私有的

console.log(toy.name); // undefined
// 公有方法访问name

console.log(toy.getName()); // "iPod"
var myobj; // 通过自执行函数给myobj赋值

(function () {

    // 自由对象

    var name = "my, oh my";
    // 实现了公有部分,所以没有var

    myobj = {

        // 授权方法

        getName: function () {

            return name;

        }

    };

} ());

模式4:Revelation模式

也是关于隐藏私有方法的模式,和《深入理解JavaScript系列(3):全面解析Module模式》里的Module模式有点类似,但是不是return的方式,而是在外部先声明一个变量,然后在内部给变量赋值公有方法。代码如下:

var myarray;
(function () {

    var astr = "[object Array]",

        toString = Object.prototype.toString;
    function isArray(a) {

        return toString.call(a) === astr;

    }
    function indexOf(haystack, needle) {

        var i = 0,

            max = haystack.length;

        for (; i < max; i += 1) {

            if (haystack[i] === needle) {

                return i;

            }

        }

        return -1;

    }
    //通过赋值的方式,将上面所有的细节都隐藏了

    myarray = {

        isArray: isArray,

        indexOf: indexOf,

        inArray: indexOf

    };

} ());
//测试代码

console.log(myarray.isArray([1, 2])); // true

console.log(myarray.isArray({ 0: 1 })); // false

console.log(myarray.indexOf(["a", "b", "z"], "z")); // 2

console.log(myarray.inArray(["a", "b", "z"], "z")); // 2
myarray.indexOf = null;

console.log(myarray.inArray(["a", "b", "z"], "z")); // 2

模式5:链模式

链模式可以你连续可以调用一个对象的方法,比如obj.add(1).remove(2).delete(4).add(2)这样的形式,其实现思路非常简单,就是将this原样返回。代码如下:

var obj = {

    value: 1,

    increment: function () {

        this.value += 1;

        return this;

    },

    add: function (v) {

        this.value += v;

        return this;

    },

    shout: function () {

        console.log(this.value);

    }

};
// 链方法调用

obj.increment().add(3).shout(); // 5
// 也可以单独一个一个调用

obj.increment();

obj.add(3);

obj.shout();

总结

本篇是对象创建模式的上篇,敬请期待明天的下篇。

Javascript 相关文章推荐
ASP SQL防注入的方法
Dec 25 Javascript
提升你网站水平的jQuery插件集合推荐
Apr 19 Javascript
js 判断脚本加载完毕的代码
Jul 13 Javascript
Jquery 动态生成表格示例代码
Dec 24 Javascript
js实现的标题栏新消息闪烁提示效果
Jun 06 Javascript
JavaScript中数组Array.sort()排序方法详解
Mar 01 Javascript
JS中touchstart事件与click事件冲突的解决方法
Mar 12 Javascript
在iFrame子页面里实现模态框的方法
Aug 17 Javascript
JS判断两个数组或对象是否相同的方法示例
Feb 28 Javascript
Vue的transition-group与Virtual Dom Diff算法的使用
Dec 09 Javascript
简单了解Vue + ElementUI后台管理模板
Apr 07 Javascript
jQuery实现倒计时功能完整示例
Jun 01 jQuery
深入理解JavaScript系列(46):代码复用模式(推荐篇)详解
Mar 04 #Javascript
深入理解JavaScript系列(45):代码复用模式(避免篇)详解
Mar 04 #Javascript
深入理解JavaScript系列(44):设计模式之桥接模式详解
Mar 04 #Javascript
JS实现FLASH幻灯片图片切换效果的方法
Mar 04 #Javascript
javascript下拉框选项单击事件的例子分享
Mar 04 #Javascript
js实现仿QQ秀换装效果的方法
Mar 04 #Javascript
深入理解JavaScript系列(43):设计模式之状态模式详解
Mar 04 #Javascript
You might like
抓取并下载CSS中所有图片文件的php代码
2011/09/26 PHP
PHP根据图片色界在不同位置加水印的方法
2015/07/01 PHP
PHP比较运算符的详细介绍
2015/09/29 PHP
PDO的安全处理与事物处理方法
2016/10/31 PHP
Prototype使用指南之ajax
2007/01/10 Javascript
jQuery库与其他JS库冲突的解决办法
2010/02/07 Javascript
利用Jquery实现可多选的下拉框
2014/02/21 Javascript
javascript实现切换td中的值
2014/12/05 Javascript
JavaScript运动减速效果实例分析
2015/08/04 Javascript
基于jQuery实现的QQ表情插件
2015/08/25 Javascript
js实现div拖动动画运行轨迹效果代码分享
2015/08/27 Javascript
jQuery获取浏览器类型和版本号的方法
2016/07/05 Javascript
基于Vuejs和Element的注册插件的编写方法
2017/07/03 Javascript
webpack构建react多页面应用详解
2017/09/15 Javascript
原生js+cookie实现购物车功能的方法分析
2017/12/21 Javascript
vue实现微信分享朋友圈,发送朋友的示例讲解
2018/02/10 Javascript
JS获取指定月份的天数两种实现方法
2018/06/22 Javascript
js实现鼠标点击飘爱心效果
2020/08/19 Javascript
跟老齐学Python之正规地说一句话
2014/09/28 Python
Python实现列表转换成字典数据结构的方法
2016/03/11 Python
Python如何获取系统iops示例代码
2016/09/06 Python
解决Python3 被PHP程序调用执行返回乱码的问题
2019/02/16 Python
深入了解Python在HDA中的应用
2019/09/05 Python
使用matplotlib的pyplot模块绘图的实现示例
2020/07/12 Python
新加坡时尚网上购物:Zalora新加坡
2016/07/26 全球购物
实习自我鉴定模板
2013/09/28 职场文书
医学院学生的自我评价分享
2013/11/19 职场文书
师范教师毕业鉴定
2014/01/13 职场文书
三年大学自我鉴定
2014/01/16 职场文书
平面设计求职信
2014/03/10 职场文书
如何写好自荐信
2014/04/07 职场文书
《云房子》教学反思
2014/04/20 职场文书
社区个人对照检查材料(群众路线)
2014/09/26 职场文书
慈善献爱心倡议书
2015/04/27 职场文书
《蚂蚁和蝈蝈》教学反思
2016/02/22 职场文书
vue Element-ui表格实现树形结构表格
2021/06/07 Vue.js