回调函数模式:
- 基本例子:
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*/);