客户端计算能力的增强,使 WEB 技术发展的天枰又开始偏向客户端运算。比如 Facebook 将模板渲染的运算放到了浏览器,浏览器先将模板下载到本地,再按需从服务器请求 JSON 格式的数据,然后在浏览器中渲染。对于提供给搜索引擎抓取的内容仍然可以在服务器端拼接完成后再输出。为了提高开发效率,可以考虑在服务器端也用 Javascript 或者其他语言拼接渲染 JSON 格式的数据和与客户端一致的模板。Mustache 就提供了这样的一种机制,并且支持大部分 WEB 语言。但是比较高效的服务器端方案仍然是用 Javascript 来写,用 NodeJS 向浏览器输出 JSON 数据和重用浏览器模板渲染代码向搜索引擎输出完整 HTML 数据。
NodeJS 和倍受推崇的 WEB 服务器 Nginx 类似,都采用 Event-driven 模型,对于单核服务器,只需要开一个进程就可以同时 serve 成千上万的客户。
不仅仅是 NodeJS, 对于 RIA 来说,支持最完善的仍然是 Javascript,基于 XUL 的客户端方案也需要 Javascript 作为开发语言,并且 Javascript 支持常见的高级特性比如 lambda,map-reduce 。
所以 Javascript 在服务器端和客户端都有很大的前景。设计模式既是解决问题的template,也是代码的组织方式。略去常见模式,仅仅涉及几个在 Javascript 中比较常用的模式:
用 prototype 的构建模式:
function Car(model, year, miles){ this.model = model; this.year = year; this.miles = miles; } /* Note here that we are using Object.prototype.newMethod rather than Object.prototype so as to avoid redefining the prototype object */ Car.prototype.toString = function(){ return this.model + " has done " + this.miles + " miles"; }; var civic = new Car("Honda Civic", 2009, 20000); var mondeo = new Car("Ford Mondeo", 2010, 5000); console.log(civic.toString());
单件模式:
var Singleton =(function(){ var instantiated; function init (){ /*singleton code here*/ return { publicMethod:function(){ console.log('hello world') }, publicProperty:'test' } } return { getInstance :function(){ if (!instantiated){ instantiated = init(); } return instantiated; } } })() /*calling public methods is then as easy as:*/ Singleton.getInstance.publicMethod();
可以传递参数的单件模式:
var SingletonTester = (function(){ //args: an object containing arguments for the singleton function Singleton(args) { //set args variable to args passed or empty object if none provided. var args = args || {}; //set the name parameter this.name = 'SingletonTester'; //set the value of pointX this.pointX = args.pointX || 6; //get parameter from arguments or set default //set the value of pointY this.pointY = args.pointY || 10; } //this is our instance holder var instance; //this is an emulation of static variables and methods var _static = { name: 'SingletonTester', //This is a method for getting an instance //It returns a singleton instance of a singleton object getInstance: function (args){ if (instance === undefined) { instance = new Singleton(args); } return instance; } }; return _static; })(); var singletonTest = SingletonTester.getInstance({pointX: 5}); console.log(singletonTest.pointX); // outputs 5
模块模式:
var someModule = (function(){ //private attributes var privateVar = 5; //private methods var privateMethod = function(){ return 'Private Test'; }; return { //public attributes publicVar : 10, //public methods publicMethod : function(){ return ' Followed By Public Test '; }, //let's access the private members getData : function(){ return privateMethod() + this.publicMethod() + privateVar; } } })(); //the parens here cause the anonymous function to execute and return someModule.getData();
观察者模式:
它适合pub-sub进行信息分发
function Observer(){ this.functions = []; } Observer.prototype = { subscribe : function(fn) { this.functions.push(fn); }, unsubscribe : function(fn) { this.functions = this.functions.filter( function(el) { if ( el !== fn ) { return el; } } ); }, update : function(o, thisObj) { var scope = thisObj || window; this.functions.forEach( function(el) { el.call(scope, o); } ); } };
/* * Publishers are in charge of "publishing" eg: Creating the Event * They're also in charge of "notifying" (firing the event) */ var obs = new Observer; obs.update('here is some test information'); /* * Subscribers basically... "subscribe" (or listen) * And once they've been "notified" their callback functions are invoked */ var fn = function() { // my callback stuff }; obs.subscribe(fn); /* * Unsubscribe if you no longer wish to be notified */ obs.unsubscribe(fn);
JQuery 中的遍历:
$.each(function(){}); $('.items').each(function(){});
更多有用资源
http://www.hunlock.com/blogs/Functional_Javascript
http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#designpatternsjavascript