介绍

本篇主要是介绍创建对象方面的模式的下篇,利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码。

模式6:函数语法糖

函数语法糖是为一个对象快速添加方法(函数)的扩展,这个主要是利用prototype的特性,代码比较简单,我们先来看一下实现代码:

if (typeof Function.prototype.method !== "function") {
Function.prototype.method = function (name, implementation) {
this.prototype[name] = implementation;
return this;
};
} 扩展对象的时候,可以这么用: var Person = function (name) {
this.name = name;
}
.method('getName',
function () {
return this.name;
})
.method('setName', function (name) {
this.name = name;
return this;
}); 这样就给Person函数添加了getName和setName这2个方法,接下来我们来验证一下结果: var a = new Person('Adam');
console.log(a.getName()); // 'Adam'
console.log(a.setName('Eve').getName()); // 'Eve' 模式7:对象常量 对象常量是在一个对象提供set,get,ifDefined各种方法的体现,而且对于set的方法只会保留最先设置的对象,后期再设置都是无效的,已达到别人无法重载的目的。实现代码如下: var constant = (function () {
var constants = {},
ownProp = Object.prototype.hasOwnProperty,
// 只允许设置这三种类型的值
allowed = {
string: 1,
number: 1,
boolean: 1
},
prefix = (Math.random() + "_").slice(2); return {
// 设置名称为name的属性
set: function (name, value) {
if (this.isDefined(name)) {
return false;
}
if (!ownProp.call(allowed, typeof value)) {
return false;
}
constants[prefix + name] = value;
return true;
},
// 判断是否存在名称为name的属性
isDefined: function (name) {
return ownProp.call(constants, prefix + name);
},
// 获取名称为name的属性
get: function (name) {
if (this.isDefined(name)) {
return constants[prefix + name];
}
return null;
}
};
} ()); 验证代码如下: // 检查是否存在
console.log(constant.isDefined("maxwidth")); // false // 定义
console.log(constant.set("maxwidth", 480)); // true // 重新检测
console.log(constant.isDefined("maxwidth")); // true // 尝试重新定义
console.log(constant.set("maxwidth", 320)); // false // 判断原先的定义是否还存在
console.log(constant.get("maxwidth")); // 模式8:沙盒模式 沙盒(Sandbox)模式即时为一个或多个模块提供单独的上下文环境,而不会影响其他模块的上下文环境,比如有个Sandbox里有3个方法event,dom,ajax,在调用其中2个组成一个环境的话,和调用三个组成的环境完全没有干扰。Sandbox实现代码如下: function Sandbox() {
// 将参数转为数组
var args = Array.prototype.slice.call(arguments),
// 最后一个参数为callback
callback = args.pop(),
// 除最后一个参数外,其它均为要选择的模块
modules = (args[0] && typeof args[0] === "string") ? args : args[0],
i; // 强制使用new操作符
if (!(this instanceof Sandbox)) {
return new Sandbox(modules, callback);
} // 添加属性
this.a = 1;
this.b = 2; // 向this对象上需想添加模块
// 如果没有模块或传入的参数为 "*" ,则以为着传入所有模块
if (!modules || modules == '*') {
modules = [];
for (i in Sandbox.modules) {
if (Sandbox.modules.hasOwnProperty(i)) {
modules.push(i);
}
}
} // 初始化需要的模块
for (i = 0; i < modules.length; i += 1) {
Sandbox.modules[modules[i]](this);
} // 调用 callback
callback(this);
} // 默认添加原型对象
Sandbox.prototype = {
name: "My Application",
version: "1.0",
getName: function () {
return this.name;
}
}; 然后我们再定义默认的初始模块: Sandbox.modules = {}; Sandbox.modules.dom = function (box) {
box.getElement = function () {
};
box.getStyle = function () {
};
box.foo = "bar";
}; Sandbox.modules.event = function (box) {
// access to the Sandbox prototype if needed:
// box.constructor.prototype.m = "mmm";
box.attachEvent = function () {
};
box.detachEvent = function () {
};
}; Sandbox.modules.ajax = function (box) {
box.makeRequest = function () {
};
box.getResponse = function () {
};
}; 调用方式如下: // 调用方式
Sandbox(['ajax', 'event'], function (box) {
console.log(typeof (box.foo));
// 没有选择dom,所以box.foo不存在
}); Sandbox('ajax', 'dom', function (box) {
console.log(typeof (box.attachEvent));
// 没有选择event,所以event里定义的attachEvent也不存在
}); Sandbox('*', function (box) {
console.log(box); // 上面定义的所有方法都可访问
}); 通过三个不同的调用方式,我们可以看到,三种方式的上下文环境都是不同的,第一种里没有foo; 而第二种则没有attachEvent,因为只加载了ajax和dom,而没有加载event; 第三种则加载了全部。 模式9:静态成员 静态成员(Static Members)只是一个函数或对象提供的静态属性,可分为私有的和公有的,就像C#或Java里的public static和private static一样。 我们先来看一下公有成员,公有成员非常简单,我们平时声明的方法,函数都是公有的,比如: // 构造函数
var Gadget = function () {
}; // 公有静态方法
Gadget.isShiny = function () {
return "you bet";
}; // 原型上添加的正常方法
Gadget.prototype.setPrice = function (price) {
this.price = price;
}; // 调用静态方法
console.log(Gadget.isShiny()); // "you bet" // 创建实例,然后调用方法
var iphone = new Gadget();
iphone.setPrice(500); console.log(typeof Gadget.setPrice); // "undefined"
console.log(typeof iphone.isShiny); // "undefined"
Gadget.prototype.isShiny = Gadget.isShiny;
console.log(iphone.isShiny()); // "you bet" 而私有静态成员,我们可以利用其闭包特性去实现,以下是两种实现方式。 第一种实现方式: var Gadget = (function () {
// 静态变量/属性
var counter = 0; // 闭包返回构造函数的新实现
return function () {
console.log(counter += 1);
};
} ()); // 立即执行 var g1 = new Gadget(); // logs 1
var g2 = new Gadget(); // logs 2
var g3 = new Gadget(); // logs 3 可以看出,虽然每次都是new的对象,但数字依然是递增的,达到了静态成员的目的。 第二种方式: var Gadget = (function () {
// 静态变量/属性
var counter = 0,
NewGadget; //新构造函数实现
NewGadget = function () {
counter += 1;
}; // 授权可以访问的方法
NewGadget.prototype.getLastId = function () {
return counter;
}; // 覆盖构造函数
return NewGadget;
} ()); // 立即执行 var iphone = new Gadget();
iphone.getLastId(); //
var ipod = new Gadget();
ipod.getLastId(); //
var ipad = new Gadget();
ipad.getLastId(); // 数字也是递增了,这是利用其内部授权方法的闭包特性实现的。 总结 这是对象创建模式的下篇,两篇一起总共9种模式,是我们在日常JavaScript编程中经常使用的对象创建模式,不同的场景起到了不同的作用,希望大家根据各自的需求选择适用的模式。 参考:http://shichuan.github.com/javascript-patterns/#object-creation-patterns 同步与推荐 本文已同步至目录索引:深入理解JavaScript系列 深入理解JavaScript系列文章,包括了原创,翻译,转载等各类型的文章,如果对你有用,请推荐支持一把,给大叔写作的动力。

深入理解JavaScript系列(48):对象创建模式(下篇)的更多相关文章

  1. 深入理解JavaScript系列(47):对象创建模式(上篇)

    介绍 本篇主要是介绍创建对象方面的模式,利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码. 模式1:命名空间(namespace) 命名空间可以减少全局命名所需的数量,避免命名冲突或过度. ...

  2. 深入理解JavaScript系列(36):设计模式之中介者模式

    介绍 中介者模式(Mediator),用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 主要内容来自:http://www ...

  3. 深入理解JavaScript系列(49):Function模式(上篇)

    介绍 本篇主要是介绍Function方面使用的一些技巧(上篇),利用Function特性可以编写出很多非常有意思的代码,本篇主要包括:回调模式.配置对象.返回函数.分布程序.柯里化(Currying) ...

  4. 深入理解JavaScript系列(46):代码复用模式(推荐篇)

    介绍 本文介绍的四种代码复用模式都是最佳实践,推荐大家在编程的过程中使用. 模式1:原型继承 原型继承是让父对象作为子对象的原型,从而达到继承的目的: function object(o) { fun ...

  5. 深入理解JavaScript系列(45):代码复用模式(避免篇)

    介绍 任何编程都提出代码复用,否则话每次开发一个新程序或者写一个新功能都要全新编写的话,那就歇菜了,但是代码复用也是有好要坏,接下来的两篇文章我们将针对代码复用来进行讨论,第一篇文避免篇,指的是要尽量 ...

  6. 深入理解JavaScript系列(42):设计模式之原型模式

    介绍 原型模式(prototype)是指用原型实例指向创建对象的种类,并且通过拷贝这些原型创建新的对象. 正文 对于原型模式,我们可以利用JavaScript特有的原型继承特性去创建对象的方式,也就是 ...

  7. 深入理解JavaScript系列(40):设计模式之组合模式

    介绍 组合模式(Composite)将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性. 常见的场景有asp.net里的控件机制(即control ...

  8. 深入理解JavaScript系列(37):设计模式之享元模式

    介绍 享元模式(Flyweight),运行共享技术有效地支持大量细粒度的对象,避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类). 享元模式可以避免大量非常相似类的开销,在程序设 ...

  9. 深入理解JavaScript系列(30):设计模式之外观模式

    介绍 外观模式(Facade)为子系统中的一组接口提供了一个一致的界面,此模块定义了一个高层接口,这个接口值得这一子系统更加容易使用. 正文 外观模式不仅简化类中的接口,而且对接口与调用者也进行了解耦 ...

随机推荐

  1. Windows7中7种不同关机模式介绍

    在Win7关机选项中一共有7种关闭方式,分别为 Switch user(切换用户), Log off(登出), Lock(锁定), Restart(重启), Sleep(睡眠), Hibernate( ...

  2. NPOI CellStyle 设置

    public class ExcelNPOIUnit { public static void SetCell(IWorkbook workbook, ISheet sheet, IRow row, ...

  3. 转载:spring boot学习

    Spring Boot学习 Spring Boot是为了简化Spring应用的创建.运行.调试.部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置. 简单来说,它提 ...

  4. Android 虚拟机访问本地服务器的地址

    http://10.0.2.2:8080/test/ 比如 localhost:8080 为 tomcat 地址,然后 test 是 tomcat 目录下 webapps 的子目录. 10.0.2.2 ...

  5. jQuery滚动到特定位置时出现

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 10分钟教你用Python实现微信自动回复

    01 前言&&效果展示 相信大家都有忙碌的时候,不可能一直守在微信上及时回复消息.但微信又不能像QQ一样设置自动回复.无妨,今天,我们就来用Python实现微信的自动回复功能吧,并且把 ...

  7. openstack 的horizon的结构

    openstack的控制台应用horizon 特点: 1.界面的显示元素进行深度封装: 将元素的后台与前台模板结合在一起.制作html整个界面有点类似搭积木组合的方式. 2.模块加载: 根据权限对ur ...

  8. 51 Nod 1007 dp

    1007 正整数分组 1 秒 131,072 KB 10 分 2 级题   将一堆正整数分为2组,要求2组的和相差最小. 例如:1 2 3 4 5,将1 2 4分为1组,3 5分为1组,两组和相差1, ...

  9. day0202 (%s)

    #格式化输出# % s d# name = input('请输入姓名')# age = input('请输入年龄')# height = input('请输入身高')# msg = "我叫% ...

  10. 修改testng源码,添加beforeMethod和afterMethod中的日志到test中(可以不改源码,废弃)

    在使用testng生成报告的时候,只会记录test方法中的日志,但是一般会在beforeMethod.beforeTest.afterMethod.afterTest中做一下数据的处理,这里面的日志没 ...