深入理解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 相关文章推荐
解放web程序员的输入验证
Oct 06 Javascript
JavaScript的eval JSON object问题
Nov 15 Javascript
js location.replace与location.reload的区别
Sep 08 Javascript
jquery弹出层类代码分享
Dec 27 Javascript
javascript基本数据类型及类型检测常用方法小结
Dec 14 Javascript
jQuery UI仿淘宝搜索下拉列表功能
Jan 10 Javascript
原生node.js案例--前后台交互
Feb 20 Javascript
Spring Boot/VUE中路由传递参数的实现代码
Mar 02 Javascript
JS多个表单数据提交下的serialize()应用实例分析
Aug 27 Javascript
js中比较两个对象是否相同的方法示例
Sep 02 Javascript
ES6中的类(Class)示例详解
Dec 09 Javascript
react如何快速设置文件路径别名
Apr 28 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 screw加密php源代码
2013/06/20 PHP
微信公众号开发之微信公共平台消息回复类实例
2014/11/14 PHP
PHP生成唯一订单号
2015/07/05 PHP
Ubuntu中支持PHP5与PHP7双版本的简单实现
2018/08/19 PHP
jQuery学习2 选择器的使用说明
2010/02/07 Javascript
Jquery Uploadify多文件上传带进度条且传递自己的参数
2013/08/28 Javascript
js(jQuery)获取时间的方法及常用时间类搜集
2013/10/23 Javascript
javascript中加var和不加var的区别 你真的懂吗
2016/01/06 Javascript
webpack 1.x升级过程中的踩坑总结大全
2017/08/09 Javascript
基于Node.js实现压缩和解压缩的方法
2018/02/13 Javascript
vue.js 使用axios实现下载功能的示例
2018/03/05 Javascript
vue实现的上传图片到数据库并显示到页面功能示例
2018/03/17 Javascript
Angular PWA使用的Demo示例
2019/01/31 Javascript
Vue匿名插槽与作用域插槽的合并和覆盖行为
2019/04/22 Javascript
微信小程序实现的图片保存功能示例
2019/04/24 Javascript
Vue 实现复制功能,不需要任何结构内容直接复制方式
2019/11/09 Javascript
js实现图片实时时钟
2020/01/15 Javascript
vue:el-input输入时限制输入的类型操作
2020/08/05 Javascript
微信小程序实现购物车小功能
2020/12/30 Javascript
Python中Continue语句的用法的举例详解
2015/05/14 Python
理想高通滤波实现Python opencv示例
2019/01/30 Python
Django之form组件自动校验数据实现
2020/01/14 Python
python+flask编写一个简单的登录接口
2020/11/13 Python
Python环境搭建过程从安装到Hello World
2021/02/05 Python
CSS3 实现倒计时效果
2020/11/25 HTML / CSS
使用canvas压缩图片上传的方法示例
2020/02/07 HTML / CSS
澳大利亚个性化儿童礼品网站:Bright Star Kids
2019/06/14 全球购物
编写类String的构造函数、析构函数和赋值函数
2012/05/29 面试题
历史专业学生的自我评价
2014/02/28 职场文书
老公爱的承诺书
2014/03/31 职场文书
党员自我对照检查材料
2014/08/19 职场文书
党员个人公开承诺书
2014/08/29 职场文书
倡议书格式
2014/08/30 职场文书
八项规定自查自纠报告及整改措施
2014/10/26 职场文书
实现GO语言对数组切片去重
2022/04/20 Golang
关于mysql中string和number的转换问题
2022/06/14 MySQL