回调函数模式:
- 基本例子:
var findNodes = function (callback) { ...................... if (typeof callback !== 'function') { callback = false; } ................ while(i) { i --; ............ if(callback) { callback(found) } ............ } }
- 回调方法是对象方法的时候:
var findNodes = function (callback, callback_obj) { ......... if(typeof callback === 'string') { callback = callback_obj[callback]; } ........... if(typeof callback === 'function') { callback.call(callnack_obj, found); } ........... }
//findNodes('paint', myapp); - 常使用情况:
- 异步事件监听器
- 超时
返回函数模式:根据输入,函数可以返回另一个更专门的函数,也可以按需创建另一个函数;
结合闭包创建的计数器的例子:
var setup = function() { var count = 0; return function () { return count++; } }
惰性函数模式:函数直到第一次使用 时才被正确地定义,并且具有向后惰性,执行了更少的工作;
var scareMe = function() { alert('Boo!'); scareMe = function() { alert('Double boo!'); } }
适用:具有仅需执行一次的初始化设定;
缺点:
- 重定义自身时,原本加上去的属性会消失或需要再次定义;
- 若赋值给其它方法,将不再具有这个功能;
即时函数模式:在函数定义之后立即执行
- 参数:一般通过括号传入
(function (a, b) {})(a, b);
- 返回值:分配给变量;
- 可以使用即时函数的作用域存储一些私有数据:
var getResult = (function () { var res = 2 + 2; return function () { return res; } })(); //可以和返回函数模式比较一下;
- 定义对象属性时也可以用即时函数:
var o = { message : (function () { ....... }()), getMsg: function() { return this.message; } }
- 可以使用即时函数的作用域存储一些私有数据:
即时对象初始化模式:
- 概念:
- 保护全局作用域不受污染的另一个方法,类似于即时函数模式;
- 这种模式使用带有init()方法的对象,该方法在创建对象后会立即执行;
- init()函数负责所有初始化任务
({ //配置常数 maxWidth : 600, maxHeigth: 400, ........... //设置一些其他方法 gimmeMax: fnction () { return this.maxWidth + 'x' + this.maxHeight; } .............. init: function () { console.log(this.getmeMax()); ............ } }).init();
- 这种模式适用于一次性任务,如果在init()完毕之后保存该对象的引用,可以在init函数尾部添加 return this;
初始化时分支模式(优化模式): 如果知道某个条件在整个生命周期内不会发生改变,可以仅对该条件测试一次;
- XMLHttpRequest的例子:
- 在每次都测试的情况下:
var utils = { addListener : function (el , type, fn) { if (typeof window.addEventListener === 'function') { el.addEventListener(type, fn, false); } else if (typeof document.attachEvent === 'function') { el.attachEvent('on' + type, fn); } else { el['on' + type] = fn; } }, removeListener: function (el, type, fn) { ........ } }
- 仅在第一次测试的情况下:
var utils = { addListener : function (el , type, fn) { }, removeListener: function (el, type, fn) { ........ } } var utils = { addListener: null, removeListener: nul } if (typeof window.addEventListener === 'function') { utils.addListener = function (el, type, fn) { el.addEventListener(type, fn, false); } utils.removeListener = function (el, type, fn) { el.removeListener (type, fn, false); } } else if (typeof document.attachEvent === 'function') { utils.addListener = function (el, type, fn) { el.attachEvenr('on' + type, fn); } utils.removeListener = function (el, type, fn) { el.detachEvenr('on' + type, fn); } } else { utils.addListener = function (el, type, fn) { el['on' + type] = fn; } utils.removeListener = function (el, type, fn) { el['on' + type] = null; } }
- 在每次都测试的情况下:
备忘模式:在适当的时候自定义属性到函数中;
var myFunc = function () { var cachekey = JSON.stringify(Array.prototype.slice.call(arguments)), result; if(!myFunc.cache[cachekey]) { result = {}; ............. myFunc.cache[cachekey] = result; } return myFunc.cache[cachekey]; } myFunc.cache = {};
配置对象模式:考虑到随着项目变化而需求变化而提供更简介的API的方法;
var conf = { username: "batman", first: "Bruce", last: 'Wayne' } addPerson(conf)
特别适用于有许多可选特征属性的情况,如创建DOM时;
Curry模式:使函数理解并处理部分应用的过程称为Curry过程;
- curry化函数:
function curry(fn) { var slice = Array.prototype.slice; stored_args = slice.call(arguments, 1); return function () { var new_args = slice.call(arguments), args = stored_args.concat(new_args); return fn.apply(null, args); } }
//
function add(a, b) {
return a + b;
}
curry(add, 6)(7); - 使用bind
function add (a, b ,c) { return a + b + c; } add.bind(null,0,1)(2 /*c*/);