[译]你应该知道的4种JavaScript设计模式
这里介绍下面这4种设计模式
- Module
- Prototype
- Observer
- Singleton
每种模式有许多属性构成,在这我只强调以下几点:
1 Context: 在何种情况使用哪种模式?
2 问题: 我们要解决什么为题?
3 解决方案: 怎么用模式解决我们的问题?
4 实现: 怎么实现这些模式?
Module
module是JavaScript里面的类。类的一个优点是封装--使得某些状态和行为不被其他的类访问. Module设计模式允许我们有私有成员和公共成员。
Module应该是IIFE(Immediately-Invoked-Function-Expressions)这样我们就能有私有作用域-它通过闭包来保护其中的私有成员(Module返回的是一个object而不是一个function).
他应该类似于下面的样子:
(function() {
// 在此声明私有变量或者函数
return {
// 在此声明公共变量或者函数
}
})();
在return一个对象之前我们声明了些变量和函数. 外部的代码无法方位我们的私有变量或函数,因为他们不在一个作用域。下面我们看一个更具体一些的例子:
var HTMLChanger = (function() {
var contents = 'contents'
var changeHTML = function() {
var element = document.getElementById('attribute-to-change');
element.innerHTML = contents;
}
return {
callChangeHTML: function() {
changeHTML();
console.log(contents);
}
};
})();
HTMLChanger.callChangeHTML(); // Outputs: 'contents'
console.log(HTMLChanger.contents); // undefined
注意callChangeHTML绑定在返回的对象里面,能在HTMLChanger命名空间中被引用。然而在此module外,contents是不能被访问的。
Revealing Module
Revealing是Module模式的一个变种。 目的是维持封装并且通过返回的对象字面量暴露一些变量和方法。他应该类似于下面的样子:
var Exposer = (function() {
var privateVariable = 10;
var privateMethod = function() {
console.log('Inside a private method!');
privateVariable++;
}
var methodToExpose = function() {
console.log('This is a method I want to expose!');
}
var otherMethodIWantToExpose = function() {
privateMethod();
}
return {
first: methodToExpose,
second: otherMethodIWantToExpose
};
})();
Exposer.first(); // Output: This is a method I want to expose!
Exposer.second(); // Output: Inside a private method!
Exposer.methodToExpose; // undefined
Prototype
为了克隆一个对象必须先要有一个用力实例化对象的构造函数。 然后通过关键字prototype来将变量和方法绑定到对象结构中。看看下面的例子:
var TeslaModelS = function() {
this.numWheels = 4;
this.manufacturer = 'Tesla';
this.make = 'Model S';
}
TeslaModelS.prototype.go = function() {
// Rotate wheels
}
TeslaModelS.prototype.stop = function() {
// Apply brake pads
}
当创建了一个TeslaModelS对象,他会保持构造函数里面初始化的状态。可以通过另外一个方法在prototype上扩展功能:
var TeslaModelS = function() {
this.numWheels = 4;
this.manufacturer = 'Tesla';
this.make = 'Model S';
}
TeslaModelS.prototype = {
go: function() {
// Rotate wheels
},
stop: function() {
// Apply brake pads
}
}
Revealing Prototype
var TeslaModelS = function() {
this.numWheels = 4;
this.manufacturer = 'Tesla';
this.make = 'Model S';
}
TeslaModelS.prototype = function() {
var go = function() {
// Rotate wheels
};
var stop = function() {
// Apply brake pads
};
return {
pressBrakePedal: stop,
pressGasPedal: go
}
}();
Observer
我们经常会遇到这样的情况当一个应用的某部分发生了改变的时候,该应用的其他部分需要被更新。在AngularJS中如果$scope对象更新了,一个事件将会被触发通知到其他的组件。观察者模式就是用来干这个事情的。
另一个例子是model-view-controller(MVC)架构;当model更新了,view会发生变化。

var Subject = function() {
this.observers = [];
return {
subscribeObserver: function(observer) {
this.observers.push(observer);
},
unsubscribeObserver: function(observer) {
var index = this.observers.indexOf(observer);
if(index > -1) {
this.observers.splice(index, 1);
}
},
notifyObserver: function(observer) {
var index = this.observers.indexOf(observer);
if(index > -1) {
this.observers[index].notify(index);
}
},
notifyAllObservers: function() {
for(var i = 0; i < this.observers.length; i++){
this.observers[i].notify(i);
};
}
};
};
var Observer = function() {
return {
notify: function(index) {
console.log("Observer " + index + " is notified!");
}
}
}
var subject = new Subject();
var observer1 = new Observer();
var observer2 = new Observer();
var observer3 = new Observer();
var observer4 = new Observer();
subject.subscribeObserver(observer1);
subject.subscribeObserver(observer2);
subject.subscribeObserver(observer3);
subject.subscribeObserver(observer4);
subject.notifyObserver(observer2); // Observer 2 is notified!
subject.notifyAllObservers();
// Observer 1 is notified!
// Observer 2 is notified!
// Observer 3 is notified!
// Observer 4 is notified!
Singleton
var printer = (function () {
var printerInstance;
function create () {
function print() {
// underlying printer mechanics
}
function turnOn() {
// warm up
// check for paper
}
return {
// public + private states and behaviors
print: print,
turnOn: turnOn
};
}
return {
getInstance: function() {
if(!printerInstance) {
printerInstance = create();
}
return printerInstance;
}
};
function Singleton () {
if(!printerInstance) {
printerInstance = intialize();
}
};
})();
var officePrinter = printer.getInstance();
[译]你应该知道的4种JavaScript设计模式的更多相关文章
- 每个IT安全专业人员应该知道的12种根本漏洞
每个IT安全专业人员应该知道的12种根本漏洞 每年,IT安全专业人员都面临着数千个新的软件漏洞和数百万个不同的恶意软件程序,但只有12种根本漏洞会让这些软件漏洞和恶意软件程序攻击你的设备.了解这些根本 ...
- [译] 你该知道的javascript作用域 (javascript scope)(转)
javascript有一些对于初学者甚至是有经验的开发者都难以理解的概念. 这个部分是针对那些听到 : 作用域, 闭包, this, 命名空间, 函数作用域, 函数作用域, 全局作用域, 变量作用域( ...
- 23种JavaScript设计模式
原文链接:https://boostlog.io/@sonuton/23-javascript-design-patterns-5adb006847018500491f3f7f 转自: https:/ ...
- 21种JavaScript设计模式最新记录(含图和示例)
最近观看了<Javascript设计模式系统讲解与应用>教程,对设计模式有了新的认识,特在此做些记录. 一.UML 文中会涉及众多的UML类图,在开篇需要做点基础概念的认识.以下面的图为例 ...
- 2018年你需要知道的13个JavaScript工具库
译者按: 你可能已经用到Underscore或者Lodash.本文列举了13个常用的JavaScript工具库来提高开发效率. 原文: 11 Javascript Utility Libraries ...
- 你应该知道的25道Javascript面试题
题目来自 25 Essential JavaScript Interview Questions.闲来无事,正好切一下. 一 What is a potential pitfall with usin ...
- 早该知道的7个JavaScript技巧
我写JavaScript代码已经很久了,都记不起是什么年代开始的了.对于JavaScript这种语言近几年所取得的成就,我感到非常的兴奋:我很幸运也是这些成就的获益者.我写了不少的文章,章节,还有一本 ...
- 你有必要知道的 25 个 JavaScript 面试题
1.使用 typeof bar === "object" 推断 bar 是不是一个对象有神马潜在的弊端?怎样避免这样的弊端? 使用 typeof 的弊端是显而易见的(这样的弊端同使 ...
- 早该知道的 7 个JavaScript 技巧[转]
简洁写法 对象的简写在过去,如果你想创建一个对象,你需要这样: var car = new Object(); car.colour = 'red'; car.wheels = 4; car.h ...
随机推荐
- windows中,端口查看&关闭进程及Kill使用
测试过程中遇到的问题,杂记一: 1.netstat -ano | findstr "8001" 查看端口8001被哪个进程占用:由下图可以看出,被进程为3736的占用 2.查 ...
- 编程语言吉祥物之Duke
在看到这个可爱的小家伙前,我一直以为那个咖啡杯子是Java的吉祥物.直到拿到<Java性能优化权威指南>这本书,才知道有这个小东西Duke.这位可爱的Duke是由Joe Palrang在1 ...
- THINKPHP源码学习--------验证码类
TP3.2验证码类的理解 今天在学习中用到了THINKPHP验证码,为了了解究竟,就开始阅读TP验证码的源码. 源码位置:./ThinkPHP/Library/Think/Verify.class.p ...
- C#递归遍历子目录与子目录中的文件
[转载]作者:weixingstudio 采用C#,通过指定一个路径,来递归的遍历所有的子目录以及子目录中的文件,建一个类似资源管理器的目录树 先递归的遍历所有的子目录,如果没有子目录以后,则遍历所有 ...
- ScrollView分栏视图分析
代码精华部分如下: //1.添加scrollView /* 1). 添加一个scrollView; 2).创建关注.热门.附近三个控制器. 3). 存储它们的名字到数组中,遍历并放到本控制器里. 4) ...
- 如何给SVG填充和描边应用线性渐变
给SVG元素应用填充和描边有三种方法(戳这里学习SVG填充和描边的相关内容).你可以使用纯色.图案或渐变.前面两种方法我们之前已经讲过了,现在我们来讨论第三种方法——渐变. SVG提供了两种渐变——线 ...
- chrome快捷键
常用的为: Ctrl + ] 下一个面板 Ctrl + [ 上一个面板 Ctrl + Alt + [ 去上一个历史记录的面板Ctrl + Alt + ] 去下一个历史记录的面板 Ct ...
- EF查询之性能优化技巧
上一篇:EF使用CodeFirst方式生成数据库&技巧经验 前言 EF相信大部分同学都已经经常使用了,可是你的查询高效吗? 今天我就以个人使用经验来讲讲在使用EF做查询的时候大家都容易忽略的性 ...
- Wannafly Union Goodbye 2016
A 题意:平面上有n个点(n<=100000),给你一个p(20<=p<=100) 判断是否存在一条直线至少过[np/100](向上取整)个点,时限20s,多组数据 分析:概率算法 ...
- Beta版本冲刺计划及安排
经过紧张的Alpha阶段,很多组已经从完全不熟悉语言和环境,到现在能够实现初步的功能.下一阶段即将加快编码进度,完成系统功能.强化软件工程的体会.Beta阶段的冲刺时间为期七天,安排在2016.12. ...