深入理解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 数组操作详解
Jan 29 Javascript
jQuery中noConflict()用法实例分析
Feb 08 Javascript
Bootstrap每天必学之折叠
Apr 12 Javascript
jQuery中的基本选择器用法学习教程
Apr 14 Javascript
AngularJS入门教程之静态模板详解
Aug 18 Javascript
浅谈js函数的多种定义方法与区别
Nov 29 Javascript
JS实现调用本地摄像头功能示例
May 18 Javascript
json 带斜杠时如何解析的实现
Aug 12 Javascript
vue+elementUi图片上传组件使用详解
Aug 20 Javascript
layer的prompt弹出框,点击回车,触发确定事件的方法
Sep 06 Javascript
js实现简易计算器功能
Oct 18 Javascript
python实现迭代法求方程组的根过程解析
Nov 25 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
MYSQL 小技巧 -- LAST_INSERT_ID
2009/11/24 PHP
解析左右值无限分类的实现算法
2013/06/20 PHP
destoon出现验证码不显示时的紧急处理方法
2014/08/22 PHP
Yii中render和renderPartial的区别
2014/09/03 PHP
PHP动态页生成静态页的3种常用方法
2014/11/13 PHP
PHP文件读取功能的应用实例
2015/05/08 PHP
关于PHP中Session文件过多的问题及session文件保存位置
2016/03/17 PHP
PHP设计模式之工厂模式实例总结
2017/09/01 PHP
TP3.2.3框架使用CKeditor编辑器在页面中上传图片的方法分析
2019/12/31 PHP
一段效率很高的for循环语句使用方法
2007/08/13 Javascript
jQuery中delegate和on的用法与区别详细解析
2014/01/26 Javascript
JavaScript必知必会(七)js对象继承
2016/06/08 Javascript
angular双向绑定模拟探索
2016/12/26 Javascript
bootstrap如何让dropdown menu按钮式下拉框长度一致
2017/04/10 Javascript
javascript/jquery实现点击触发事件的方法分析
2019/11/11 jQuery
vue+导航锚点联动-滚动监听和点击平滑滚动跳转实例
2019/11/13 Javascript
VUE中setTimeout和setInterval自动销毁案例
2020/09/07 Javascript
antd日期选择器禁止选择当天之前的时间操作
2020/10/29 Javascript
[28:48]《真视界》- 2017年国际邀请赛
2017/09/27 DOTA
Python中你应该知道的一些内置函数
2017/03/31 Python
解决Django的request.POST获取不到内容的问题
2018/05/28 Python
使用pytorch进行图像的顺序读取方法
2018/07/27 Python
pyqt远程批量执行Linux命令程序的方法
2019/02/14 Python
Python GUI库Tkiner使用方法代码示例
2020/11/27 Python
全球采购的街头服饰和帽子:Urban Excess
2020/10/28 全球购物
是什么让J2EE适合用来开发多层的分布式的应用
2015/01/16 面试题
聚网科技C++面试笔试题
2015/09/01 面试题
以思科路由器为例你写下单臂路由的配置命令
2013/08/03 面试题
经典优秀个人求职自荐信格式
2013/09/25 职场文书
安全标准化实施方案
2014/02/20 职场文书
产品质量承诺范本
2014/03/31 职场文书
幼儿园教师演讲稿
2014/05/06 职场文书
2015年新农村建设工作总结
2015/05/22 职场文书
一年级语文教学随笔
2015/08/14 职场文书
Nginx中使用Lua脚本与图片的缩略图处理的实现
2022/03/18 Servers
python函数的两种嵌套方法使用
2022/04/02 Python