深入理解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 相关文章推荐
JavaScript 事件查询综合
Jul 13 Javascript
Document 对象的常用方法
Jul 31 Javascript
jquery 注意事项与常用语法小结
Jun 07 Javascript
JS获取鼠标坐标的实例方法
Jul 18 Javascript
一个JS的日期格式化算法示例
Jul 31 Javascript
ExtJs纵坐标值重复问题的解决方法
Feb 27 Javascript
jQuery无刷新切换主题皮肤实例讲解
Oct 21 Javascript
js转换对象为xml
Feb 17 Javascript
Vue自定义指令详解
Jul 28 Javascript
JavaScript中递归实现的方法及其区别
Sep 12 Javascript
JavaScript数据结构之双向链表和双向循环链表的实现
Nov 28 Javascript
JavaScript设计模式之原型模式详情
Jun 21 Javascript
深入理解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
PHPwind整合最土系统用户同步登录实现方法
2010/12/08 PHP
php图片上传存储源码并且可以预览
2011/08/26 PHP
php使用Jpgraph创建3D饼形图效果示例
2017/02/15 PHP
PHP正则匹配到2个字符串之间的内容方法
2018/12/24 PHP
java解析json方法总结
2019/05/16 PHP
Laravel 集成微信用户登录和绑定的实现
2019/12/27 PHP
超级兔子让浮动层消失的前因后果
2007/03/09 Javascript
JavaScript获得选中文本内容的方法
2008/12/02 Javascript
用XMLDOM和ADODB.Stream实现base64编码解码实现代码
2010/11/28 Javascript
通过JS自动隐藏手机浏览器的地址栏实现原理与代码
2013/01/02 Javascript
js获取input标签的输入值实现代码
2013/08/05 Javascript
纯javascript实现图片延时加载方法
2015/08/21 Javascript
js实现延时加载Flash的方法
2015/11/26 Javascript
学习使用grunt来打包JavaScript和CSS程序的教程
2016/01/04 Javascript
JS拖拽组件学习使用
2016/01/19 Javascript
bootstrap表格分页实例讲解
2016/12/30 Javascript
解决在vue+webpack开发中出现两个或多个菜单公用一个组件问题
2017/11/28 Javascript
如何手动实现一个 JavaScript 模块执行器
2020/10/16 Javascript
nestjs返回给前端数据格式的封装实现
2021/02/22 Javascript
简单介绍Python中的readline()方法的使用
2015/05/24 Python
python正则分析nginx的访问日志
2017/01/17 Python
Python 通过URL打开图片实例详解
2017/06/01 Python
python 利用栈和队列模拟递归的过程
2018/05/29 Python
Python数据分析:手把手教你用Pandas生成可视化图表的教程
2018/12/15 Python
对python的unittest架构公共参数token提取方法详解
2018/12/17 Python
详解python中的模块及包导入
2019/08/30 Python
python文件操作的简单方法总结
2019/11/07 Python
Python统计文本词汇出现次数的实例代码
2020/02/27 Python
python 安装impala包步骤
2020/03/28 Python
Python基于paramunittest模块实现excl参数化
2020/04/26 Python
Python txt文件常用读写操作代码实例
2020/08/03 Python
美国伊甸园兄弟种子公司:Eden Brothers
2018/07/01 全球购物
党课心得体会范文
2014/09/09 职场文书
酒店销售经理岗位职责
2015/04/02 职场文书
欢送会主持词
2015/07/01 职场文书
爱国主题班会教案
2015/08/14 职场文书