深入理解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文件后面跟参数的原因说明
Jan 09 Javascript
Ext 今日学习总结
Sep 19 Javascript
JavaScript操作XML 使用百度RSS作为新闻源示例
Feb 17 Javascript
JSONP跨域GET请求解决Ajax跨域访问问题
Dec 31 Javascript
JavaScript编程中布尔对象的基本使用
Oct 25 Javascript
Javascript基础知识盲点总结之函数
May 15 Javascript
Vue.js框架路由使用方法实例详解
Aug 25 Javascript
微信小程序动态生成二维码的实现代码
Jul 25 Javascript
VUE在for循环里面根据内容值动态的加入class值的方法
Aug 12 Javascript
浅谈Angular单元测试总结
Mar 22 Javascript
微信小程序tab切换可滑动切换导航栏跟随滚动实现代码
Sep 04 Javascript
手把手教您实现react异步加载高阶组件
Apr 07 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
curl不使用文件存取cookie php使用curl获取cookie示例
2014/01/26 PHP
php生成带logo二维码方法小结
2016/04/08 PHP
Thinkphp框架 表单自动验证登录注册 ajax自动验证登录注册
2016/12/27 PHP
Laravel 解决composer相关操作提示php相关异常的问题
2019/10/23 PHP
js 动态加载事件的几种方法总结
2013/12/25 Javascript
jquery判断复选框是否选中进行答题提示特效
2015/12/10 Javascript
原生js封装二级城市下拉列表的实现代码
2016/06/16 Javascript
AngularJS 应用身份认证的技巧总结
2016/11/07 Javascript
Bootstrap的popover(弹出框)2秒后定时消失的实现代码
2017/02/27 Javascript
JS中mouseup事件丢失的原因与解决办法
2017/06/14 Javascript
vue.js+element-ui动态配置菜单的实例
2018/09/07 Javascript
JavaScript动态添加数据到表单并提交的几种方式
2019/06/26 Javascript
[01:59]DOTA2首部纪录片《Free to play》预告片
2014/03/12 DOTA
python实现ipsec开权限实例
2014/11/11 Python
Python中subprocess模块用法实例详解
2015/05/20 Python
python计算文本文件行数的方法
2015/07/06 Python
Windows中使用wxPython和py2exe开发Python的GUI程序的实例教程
2016/07/11 Python
简单学习Python多进程Multiprocessing
2017/08/29 Python
Django+Ajax+jQuery实现网页动态更新的实例
2018/05/28 Python
3分钟学会一个Python小技巧
2018/11/23 Python
python PyQt5/Pyside2 按钮右击菜单实例代码
2019/08/17 Python
python如何从文件读取数据及解析
2019/09/19 Python
python opencv图片编码为h264文件的实例
2019/12/12 Python
浅谈tensorflow中dataset.shuffle和dataset.batch dataset.repeat注意点
2020/06/08 Python
警察思想汇报
2014/01/04 职场文书
竞聘上岗演讲稿范文
2014/01/10 职场文书
铁路安全事故反思
2014/04/26 职场文书
企业年度评优方案
2014/06/02 职场文书
个人查摆剖析材料
2014/10/16 职场文书
大学生见习报告总结
2014/11/04 职场文书
2014年酒店前台工作总结
2014/11/14 职场文书
2015年元旦标语大全
2014/12/09 职场文书
干部外出学习心得体会
2016/01/18 职场文书
2016医师资格考试考生诚信考试承诺书
2016/03/25 职场文书
Python实战之实现简易的学生选课系统
2021/05/25 Python
Win11运行育碧游戏总是崩溃怎么办 win11玩育碧游戏出现性能崩溃的解决办法
2022/04/06 数码科技