深入理解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 相关文章推荐
一个选择最快的服务器转向代码
Apr 27 Javascript
asp.net网站开发中用jquery实现滚动浏览器滚动条加载数据(类似于腾讯微博)
Mar 14 Javascript
js操作输入框提示信息且响应鼠标事件
Mar 25 Javascript
js delete 用法(删除对象属性及变量)
Aug 24 Javascript
vue如何根据网站路由判断页面主题色详解
Nov 02 Javascript
浅谈Vue的响应式原理
May 30 Javascript
layui数据表格跨行自动合并的例子
Sep 02 Javascript
JS工厂模式开发实践案例分析
Oct 17 Javascript
如何在Node和浏览器控制台中打印彩色文字
Jan 09 Javascript
js获取url页面id,也就是最后的数字文件名
Sep 25 Javascript
详解Vue.js3.0 组件是如何渲染为DOM的
Nov 10 Javascript
一篇文章告诉你如何实现Vue前端分页和后端分页
Feb 18 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判断数组中是否存在指定键(key)的方法
2015/03/17 PHP
php保存任意网络图片到服务器的方法
2015/04/14 PHP
thinkPHP自动验证、自动添加及表单错误问题分析
2016/10/17 PHP
在JavaScript中监听IME键盘输入事件
2011/05/29 Javascript
实例讲解JS中数组Array的操作方法
2014/05/09 Javascript
从零学JSON之JSON数据结构
2014/05/19 Javascript
scrollWidth,clientWidth,offsetWidth的区别
2015/01/13 Javascript
JavaScript中的对象和原型(一)
2016/08/12 Javascript
基于jQuery实现数字滚动效果
2017/01/16 Javascript
快速掌握jQuery插件开发
2017/01/19 Javascript
vue点击input弹出带搜索键盘并监听该元素的方法
2018/08/25 Javascript
vue3.0 CLI - 2.1 -  component 组件入门教程
2018/09/14 Javascript
vue 利用路由守卫判断是否登录的方法
2018/09/29 Javascript
vue无限轮播插件代码实例
2019/05/10 Javascript
js 动态校验开始结束时间的实现代码
2020/05/25 Javascript
举例讲解Python的Tornado框架实现数据可视化的教程
2015/05/02 Python
Python 3.x 连接数据库示例(pymysql 方式)
2017/01/19 Python
python 数据的清理行为实例详解
2017/07/12 Python
Python实现JS解密并爬取某音漫客网站
2020/10/23 Python
HTML5实现一个能够移动的小坦克示例代码
2013/09/02 HTML / CSS
HTML5中的autofocus(自动聚焦)属性介绍
2014/04/23 HTML / CSS
HTML5响应式(自适应)网页设计的实现
2017/11/17 HTML / CSS
高级文秘工作总结的自我评价
2013/09/28 职场文书
最新自我评价范文
2013/11/16 职场文书
财务部岗位职责
2013/11/19 职场文书
写给女朋友的检讨书
2014/01/28 职场文书
给面试官的感谢信
2014/02/01 职场文书
个人工作表现评语
2014/04/30 职场文书
防沙治沙典型材料
2014/05/07 职场文书
生物技术专业求职信
2014/06/10 职场文书
2014年党员发展工作总结
2014/12/02 职场文书
舞蹈社团活动总结
2015/05/07 职场文书
学历证明样本
2015/06/16 职场文书
房屋质量投诉书
2015/07/02 职场文书
python数据库批量插入数据的实现(executemany的使用)
2021/04/30 Python
Python快速优雅的批量修改Word文档样式
2021/05/20 Python