深入理解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里使用php代码实例
Dec 13 Javascript
js中class的点击事件没有效果的解决方法
Oct 13 Javascript
jQuery中用on绑定事件时需注意的事项
Mar 19 Javascript
Angular.JS中指令ng-if、ng-show/ng-hide和ng-switch的使用教程
May 07 Javascript
JS实现新建文件夹功能
Jun 17 Javascript
基于原生js运动方式关键点的总结(推荐)
Oct 01 Javascript
JavaScript折半查找(二分查找)算法原理与实现方法示例
Aug 06 Javascript
vue.js提交按钮时进行简单的if判断表达式详解
Aug 08 Javascript
javascript面向对象三大特征之封装实例详解
Jul 24 Javascript
bootstrap-paginator服务器端分页使用方法详解
Feb 13 Javascript
JavaScript实现沿五角星形线摆动的小圆实例详解
Jul 28 Javascript
如何使用 JavaScript 操作浏览器历史记录 API
Nov 24 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
php魔术方法与魔术变量、内置方法与内置变量的深入分析
2013/06/03 PHP
php实现执行某一操作时弹出确认、取消对话框
2013/12/30 PHP
PHP获取windows登录用户名的方法
2014/06/24 PHP
php去除字符串中空字符的常用方法小结
2015/03/17 PHP
php简单日历函数
2015/10/28 PHP
关于IE7 IE8弹出窗口顶上
2008/12/22 Javascript
JavaScript通过元素索引号删除数组中对应元素的方法
2015/03/18 Javascript
js console.log打印对像与数组用法详解
2016/01/21 Javascript
如何使用jquery修改css中带有!important的样式属性
2016/04/28 Javascript
KnockoutJS 3.X API 第四章之数据控制流with绑定
2016/10/10 Javascript
使用jquery如何获取时间
2016/10/13 Javascript
AngularJS基于ui-route实现深层路由的方法【路由嵌套】
2016/12/14 Javascript
基于node.js制作简单爬虫教程
2017/06/29 Javascript
详解React 在服务端渲染的实现
2017/11/16 Javascript
Node层模拟实现multipart表单的文件上传示例
2018/01/02 Javascript
Python中自定义函数的教程
2015/04/27 Python
Python实现爬虫设置代理IP和伪装成浏览器的方法分享
2018/05/07 Python
python多线程http压力测试脚本
2019/06/25 Python
python实现控制电脑鼠标和键盘,登录QQ的方法示例
2019/07/06 Python
解决Django连接db遇到的问题
2019/08/29 Python
基于python3生成标签云代码解析
2020/02/18 Python
Python填充任意颜色,不同算法时间差异分析说明
2020/05/16 Python
解决windows上安装tensorflow时报错,“DLL load failed: 找不到指定的模块”的问题
2020/05/20 Python
基于CSS3特效之动画:animation的应用
2013/05/09 HTML / CSS
美国在线宠物用品商店:Entirely Pets
2017/01/01 全球购物
Ralph Lauren意大利官方网站:时尚界最负盛名的品牌之一
2018/10/18 全球购物
澳大利亚在线家具、灯饰和家居装饰店:LivingStyles
2018/11/20 全球购物
ellesse美国官方商店:意大利高级运动服品牌
2019/10/29 全球购物
用你熟悉的语言写一个连接ORACLE数据库的程序,能够完成修改和查询工作
2012/06/11 面试题
初中教师个人工作总结
2015/02/10 职场文书
三潭印月的导游词
2015/02/12 职场文书
Go各时间字符串使用解析
2021/04/02 Golang
教你如何使用Python Tkinter库制作记事本
2021/06/10 Python
CSS font-variation 可变字体的魅力(实例详解)
2022/03/03 HTML / CSS
Redis 操作多个数据库的配置的方法实现
2022/03/23 Redis
MySQL中TIMESTAMP类型返回日期时间数据中带有T的解决
2022/12/24 MySQL