深入理解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 相关文章推荐
js和css写一个可以自动隐藏的悬浮框
Mar 05 Javascript
jQuery中:visible选择器用法实例
Dec 30 Javascript
理解Javascript的call、apply
Dec 16 Javascript
浅谈Sublime Text 3运行JavaScript控制台
Jun 06 Javascript
JS 日期与时间戮相互转化的简单实例
Jun 22 Javascript
Web 开发中Ajax的Session 超时处理方法
Jan 19 Javascript
layui监听select变化,以及设置radio选中的方法
Sep 24 Javascript
vue 根据选择条件显示指定参数的例子
Nov 09 Javascript
基于Angular 8和Bootstrap 4实现动态主题切换的示例代码
Feb 11 Javascript
js实现简单五子棋游戏
May 28 Javascript
解决vant title-active-color与title-inactive-color不生效问题
Nov 03 Javascript
Vue Element UI自定义描述列表组件
May 18 Vue.js
深入理解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
PHP学习之字符串比较和查找
2011/04/17 PHP
fgetcvs在linux的问题
2012/01/15 PHP
php小经验:解析preg_match与preg_match_all 函数
2013/06/29 PHP
ECshop 迁移到 PHP7版本时遇到的兼容性问题
2016/02/15 PHP
Laravel实现自定义错误输出内容的方法
2016/10/10 PHP
phpStudy配置多站点多域名和多端口的方法
2017/09/01 PHP
js中的事件捕捉模型与冒泡模型实例分析
2015/01/10 Javascript
JavaScript实现点击文字切换登录窗口的方法
2015/05/11 Javascript
js实现的彩色方块飞舞奇幻效果
2016/01/27 Javascript
JavaScript优化以及前段开发小技巧
2017/02/02 Javascript
js如何编写简单的ajax方法库
2017/08/02 Javascript
移动端效果之Swiper详解
2017/10/09 Javascript
详解Puppeteer前端自动化测试实践
2019/02/21 Javascript
ES6中字符串的使用方法扩展
2019/06/04 Javascript
Node.js在图片模板上生成二维码图片并附带底部文字说明实现详解
2019/08/07 Javascript
基于vue-cli3和element实现登陆页面
2019/11/13 Javascript
[01:07:19]2018DOTA2亚洲邀请赛 4.5 淘汰赛 Mineski vs VG 第一场
2018/04/06 DOTA
Python的SQLAlchemy框架使用入门
2015/04/29 Python
python杀死一个线程的方法
2015/09/06 Python
Python实现删除文件中含“指定内容”的行示例
2017/06/09 Python
python 3.0 模拟用户登录功能并实现三次错误锁定
2017/11/01 Python
pandas.DataFrame删除/选取含有特定数值的行或列实例
2018/11/07 Python
详解python配置虚拟环境
2019/04/08 Python
Django框架 querySet功能解析
2019/09/04 Python
PyTorch实现更新部分网络,其他不更新
2019/12/31 Python
Html5 video标签视频的最佳实践
2020/02/26 HTML / CSS
租租车:国际租车、美国租车、欧洲租车、特价预订国外租车(中文服务)
2018/03/28 全球购物
巴西购物网站:Estrela10
2018/12/13 全球购物
公安交警个人对照检查材料思想汇报
2014/10/01 职场文书
钱学森电影观后感
2015/06/04 职场文书
个人催款函范文
2015/06/24 职场文书
莫言获奖感言(全文)
2015/07/31 职场文书
六五普法心得体会2016
2016/01/21 职场文书
《确定位置》教学反思
2016/02/18 职场文书
Python Pandas常用函数方法总结
2021/06/15 Python
vue实现拖拽交换位置
2022/04/07 Vue.js