深入理解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编程起步(第六课)
Feb 27 Javascript
ExtJs Excel导出并下载IIS服务器端遇到的问题
Sep 16 Javascript
js简单的弹出框有关闭按钮
May 05 Javascript
JavaScript字符串对象toLowerCase方法入门实例(用于把字母转换为小写)
Oct 17 Javascript
微信小程序使用第三方库Immutable.js实例详解
Sep 27 Javascript
jQuery延迟执行的实现方法
Dec 21 Javascript
javaScript中封装的各种写法示例(推荐)
Jul 03 Javascript
微信小程序显示下拉列表功能【附源码下载】
Dec 12 Javascript
VUE中V-IF条件判断改变元素的样式操作
Aug 09 Javascript
ES11屡试不爽的新特性,你用上了几个
Oct 21 Javascript
js实现限定范围拖拽的示例
Oct 26 Javascript
在vue中import()语法不能传入变量的问题及解决
Apr 01 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 jquery 实现新闻标签分类与无刷新分页
2009/12/18 PHP
php 无极分类(递归)实现代码
2010/01/05 PHP
PHP从二维数组得到N层分类树的实现代码
2016/10/11 PHP
PHP基于反射机制实现插件的可插拔设计详解
2016/11/10 PHP
PHP实现计算器小功能
2020/08/28 PHP
JS支持带x身份证号码验证函数
2008/08/10 Javascript
javascript 通用简单的table选项卡实现
2010/05/07 Javascript
浏览器打开层自动缓慢展开收缩实例代码
2013/07/04 Javascript
node.js中的fs.futimesSync方法使用说明
2014/12/17 Javascript
js+css实现导航效果实例
2015/02/10 Javascript
表单中单选框添加选项和移除选项
2016/07/04 Javascript
webuploader模态框ueditor显示问题解决方法
2016/12/27 Javascript
Vue.js进行查询操作的实例详解
2017/08/25 Javascript
微信小程序实现发红包功能
2018/07/11 Javascript
详解JSON Web Token 入门教程
2018/07/30 Javascript
vue组件tabbar使用方法详解
2018/11/06 Javascript
详解vue移动端项目代码拆分记录
2019/03/15 Javascript
Vue.js轮播图走马灯代码实例(全)
2019/05/08 Javascript
解决Idea、WebStorm下使用Vue cli脚手架项目无法使用Webpack别名的问题
2019/10/11 Javascript
vue项目在webpack2实现移动端字体自适配功能
2020/06/02 Javascript
vue项目开启Gzip压缩和性能优化操作
2020/10/26 Javascript
python调用短信猫控件实现发短信功能实例
2014/07/04 Python
python中的计时器timeit的使用方法
2017/10/20 Python
Python对象中__del__方法起作用的条件详解
2018/11/01 Python
解决Python下imread,imwrite不支持中文的问题
2018/12/05 Python
使用python 打开文件并做匹配处理的实例
2019/01/02 Python
使用python实现数组、链表、队列、栈的方法
2019/12/20 Python
python读取mysql数据绘制条形图
2020/03/25 Python
css3实现顶部社会化分享按钮示例
2014/05/06 HTML / CSS
H5 meta小结(前端必看篇)
2016/08/24 HTML / CSS
5.12护士节演讲稿
2014/04/30 职场文书
学校花圃的标语
2014/06/18 职场文书
公司员工活动策划方案
2014/08/20 职场文书
学生吸烟检讨书
2014/09/14 职场文书
2015年化验员工作总结
2015/04/10 职场文书
68句权威创业名言
2019/08/26 职场文书