深入理解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 相关文章推荐
我也种棵OO树JXTree[js+css+xml]
Apr 02 Javascript
说说掌握JavaScript语言的思想前提想学习js的朋友可以看看
Apr 01 Javascript
asp.net下利用js实现返回上一页的实现方法小集
Nov 24 Javascript
jQuery实现新消息闪烁标题提示的方法
Mar 11 Javascript
浅谈Sizzle的“编译原理”
Apr 14 Javascript
jQuery插件imgAreaSelect基础讲解
May 26 jQuery
JS中Map和ForEach的区别
Feb 05 Javascript
详解js的视频和音频采集
Aug 09 Javascript
JavaScript中Array方法你该知道的正确打开方法
Sep 11 Javascript
JavaScript 截取字符串代码实例
Sep 05 Javascript
JavaScript实现英语单词题库
Dec 24 Javascript
vue单元格多列合并的实现
Nov 26 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使用ftp实现文件上传与下载功能
2017/07/21 PHP
PHP使用PDO访问oracle数据库的步骤详解
2017/09/29 PHP
PHP长连接实现与使用方法详解
2018/02/11 PHP
PHP实现获取文件mime类型多种方法解析
2020/05/28 PHP
非阻塞动态加载javascript广告实现代码
2010/11/17 Javascript
用js实现判断当前网址的来路如果不是指定的来路就跳转到指定页面
2011/05/02 Javascript
Javascript学习笔记之 函数篇(一) : 函数声明和函数表达式
2014/06/24 Javascript
js获取IP地址的方法小结
2014/07/01 Javascript
基于jQuery实现的扇形定时器附源码下载
2015/10/20 Javascript
分享自己用JS做的扫雷小游戏
2016/02/17 Javascript
Bootstrap每天必学之标签页(Tab)插件
2020/08/09 Javascript
Laravel中常见的错误与解决方法小结
2016/08/30 Javascript
对于input 框限定输入值为浮点型的js代码
2017/09/25 Javascript
angular ng-model 无法获取值的处理方法
2018/10/02 Javascript
javascript实现弹幕墙效果
2019/11/28 Javascript
node使用async_hooks模块进行请求追踪
2021/01/28 Javascript
[14:19]2018年度COSER大赛-完美盛典
2018/12/16 DOTA
Python入门教程之if语句的用法
2015/05/14 Python
Python+OpenCV图片局部区域像素值处理改进版详解
2019/01/23 Python
ipad上运行python的方法步骤
2019/10/12 Python
Pytorch .pth权重文件的使用解析
2020/02/14 Python
html5生成柱状图(条形图)效果的实例代码
2016/03/25 HTML / CSS
美国名牌香水折扣网站:Hottperfume
2021/02/10 全球购物
比较基础的php面试题及答案-编程题
2012/10/14 面试题
软件生产职位结构化面试主要考察要素及面试题库
2015/06/12 面试题
晚宴邀请函范文
2014/01/15 职场文书
学生党员公开承诺书
2014/05/28 职场文书
综艺节目策划方案
2014/06/13 职场文书
秋季运动会演讲稿
2014/09/16 职场文书
2014年助理工程师工作总结
2014/11/14 职场文书
2015年公司国庆放假通知
2015/07/30 职场文书
2016年校长新年寄语
2015/08/17 职场文书
《秋思》教学反思
2016/02/23 职场文书
深入解析NumPy中的Broadcasting广播机制
2021/05/30 Python
【海涛教你打DOTA】剑圣第一人称视角解说
2022/04/01 DOTA
Windows11 Insider Preview Build 25206今日发布 更新内容汇总
2022/09/23 数码科技