深入理解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 相关文章推荐
Cookie 注入是怎样产生的
Apr 08 Javascript
javascript中的undefined 与 null 的区别  补充篇
Mar 17 Javascript
判断对象是否Window的实现代码
Jan 10 Javascript
CSS+JS实现点击文字弹出定时自动关闭DIV层菜单的方法
May 12 Javascript
JavaScript动态提示输入框输入字数的方法
Jul 27 Javascript
Javascript基于AJAX回调函数传递参数实例分析
Dec 15 Javascript
jQuery ready()和onload的加载耗时分析
Sep 08 Javascript
Ionic3实现图片瀑布流布局
Aug 09 Javascript
Promise.all中对于reject的处理方法
Aug 01 Javascript
jQuery实现的点击显示隐藏下拉菜单功能完整示例
May 17 jQuery
cordova+vue+webapp使用html5获取地理位置的方法
Jul 06 Javascript
JS插入排序简单理解与实现方法分析
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
神族 Protoss 历史背景
2020/03/14 星际争霸
PHP实现基于栈的后缀表达式求值功能
2017/11/10 PHP
php高性能日志系统 seaslog 的安装与使用方法分析
2020/02/29 PHP
javascript 火狐(firefox)不显示本地图片问题解决
2008/07/05 Javascript
js动态删除div元素基本思路及实现代码
2014/05/08 Javascript
JavaScript代码复用模式详解
2014/11/07 Javascript
nodejs教程之异步I/O
2014/11/21 NodeJs
基于jQuery实现表单提交验证
2014/11/24 Javascript
JQuery中clone方法复制节点
2015/05/18 Javascript
jquery实现带缩略图的可定制高度画廊效果(5种)
2015/08/28 Javascript
解析微信JS-SDK配置授权,实现分享接口
2016/12/09 Javascript
canvas绘制的直线动画
2017/01/23 Javascript
BootStrap table删除指定行的注意事项(笔记整理)
2017/02/05 Javascript
详解vue.js的事件处理器v-on:click
2017/06/27 Javascript
vue利用better-scroll实现轮播图与页面滚动详解
2017/10/20 Javascript
Vue混入mixins滚动触底的方法
2019/11/22 Javascript
[02:56]《DAC最前线》之国外战队抵达上海备战亚洲邀请赛
2015/01/28 DOTA
[02:41]辉夜杯现场一家三口 “我爸玩风行 我玩血魔”
2015/12/27 DOTA
[00:14]护身甲盾
2019/03/06 DOTA
Python对列表排序的方法实例分析
2015/05/16 Python
Python3.5 创建文件的简单实例
2018/04/26 Python
Python异常处理例题整理
2019/07/07 Python
python使用beautifulsoup4爬取酷狗音乐代码实例
2019/12/04 Python
django inspectdb 操作已有数据库数据的使用步骤
2021/02/07 Python
EVE LOM英国官网:全世界最好的洁面膏
2017/10/30 全球购物
罗马尼亚购物网站:Vivantis.ro
2019/07/20 全球购物
医学毕业生自我鉴定
2013/10/30 职场文书
环保专业大学生职业规划设计
2014/01/10 职场文书
会计电算化个人求职信范文
2014/01/24 职场文书
高中体育教学反思
2014/01/24 职场文书
高二政治教学反思
2014/02/01 职场文书
ktv总经理岗位职责
2014/02/17 职场文书
幼儿园植树节活动总结
2014/07/04 职场文书
师德标兵先进事迹材料
2014/12/19 职场文书
2019西餐厅创业计划书范文!
2019/07/12 职场文书
简单介绍 http请求响应参数、无连接无状态、MIME、状态码、端口、telnet、curl
2021/03/31 HTML / CSS