1.回調(diào)
函數(shù)讓不連續(xù)的事件處理變得容易起來
下面我們來看一個同步的傳統(tǒng)的例子
var request = prepare_request(); // 請求預(yù)處理
var response = send_request_sync(request); // 發(fā)送請求到客戶端
display(response); // 處理服務(wù)器響應(yīng)
上述的例子是同步發(fā)送的鸣个,如果服務(wù)器響應(yīng)過慢宦棺,那么會出現(xiàn)客戶端假死的現(xiàn)象
因此我們需要使用異步的方式,完成客戶端與服務(wù)器端的交互
var request = prepare_request(); // 請求預(yù)處理
send_request_asyc(request, function (response) {
display(response);
});
// 我們傳遞函數(shù)作為參數(shù)發(fā)送給send_request_asyc萌狂,當(dāng)服務(wù)器響應(yīng)后進行處理
2.模塊
模塊是一個提供了接口但是隱藏了狀態(tài)與實現(xiàn)函數(shù)的函數(shù)或者對象
我們可以用函數(shù)和閉包來構(gòu)成模塊
模塊可以使我們完全摒棄全局變量的作用
下面我們來看一個有關(guān)與解析實體字符為html標(biāo)簽的例子
Function.prototype.method = function (name, fun) {
// 如果添加的方法不存在,才可以添加
if(!this.prototype[name]) {
this.prototype[name] = fun;
return this;
}
}
String.method("deentityify", function () {
// 私有屬性對象
var entity = {
quot : '"',
lt : "<",
gt : ">"
}
// 創(chuàng)建可以返回且可以訪問entity私有變量的特權(quán)方法
return function () {
// 匹配以&開始穿扳,以;結(jié)束,且中間的字符不能為&或者;開頭的字符
// this代表調(diào)用此函數(shù)的字符串
return this.replace(/&([^&;]+);/g, function (a, b) {
var r = entity[b];
// alert(a); // < " > &ddd;
// alert(alert(b));// lt undefined quot undefined gt undefined ddd
return typeof r === "string" ? r : a;
});
}
}());
document.writeln("<">&ddd;".deentityify()); // <">&ddd;
模塊的一般形式:
一個定義了私有變量或者函數(shù)的函數(shù)国旷,
利用閉包創(chuàng)建可以訪問到私有變量或者函數(shù)的特權(quán)方法矛物,
最后返回這個特權(quán)方法,或者將其存放到一個可以訪問的地方跪但。
接下來我們要構(gòu)建一個可以生成序列化的模塊
var serial_maker = function () {
// 定義兩個私有的變量履羞,前綴和序列號
var prex = '';
var seq = 0;
// 返回一個可以訪問私有變量的對象
return {
setPrex : function (p) {
prex = String(p);
},
setSeq : function (s) {
seq = Number(s);
},
gensyn : function () {
var result = prex + seq;
seq++;
return result;
}
};
};
var maker = serial_maker();
maker.setPrex("U");
maker.setSeq(200);
alert(maker.gensyn()); // U200
maker.setPrex("Q");
alert(maker.gensyn()); // Q200
3.級聯(lián)
一些方法,例如修改和設(shè)置屡久,沒有返回值忆首,默認為undefined,
我們可以讓他們返回this被环,這樣這個方法就開啟了級聯(lián)糙及,即可以依次調(diào)用同一個對象的許多方法
getElement("div").move(200, 200).setBackground("#ccc").....; //這個div可以一次性完成許多工作
4.套用
套用允許我們將函數(shù)與傳遞給它的參數(shù)結(jié)合產(chǎn)生新函數(shù)
var add = function (a, b) {
return a + b;
}
Function.method("curry", function () {
var slice = Array.prototype.slice;
// 取得外部參數(shù),即下面實例的10
var args = slice.apply(arguments);
alert(args); // 10
var that = this;
alert(this); // 調(diào)用curry的函數(shù)筛欢,即a下面實例的add()方法
return function () {
alert(this); // [object Window]
return that.apply(null, args.concat(slice.apply(arguments)));
}
});
var add1 = add.curry(10);
alert(add1(100)); // 110
5.記憶
函數(shù)可以讓對象記住先前操作的結(jié)果浸锨,這樣就避免了無謂的計算
下面來看一個例子
var fibonacci = function (n) {
return n < 2 ? n : arguments.callee(n - 1) + arguments.callee(n - 2);
}
var start = Date.now();
for(var i = 0; i <= 30; i++) {
if (i == 30) {
document.writeln("http:// " + i + " : " + fibonacci(i) + "<br/>");
}
}
var end = Date.now();
document.writeln("原始使用時間: " + (end - start) + "<br/>"); // 用時1360
據(jù)統(tǒng)計,fibonacci函數(shù)被調(diào)用了453次版姑,我們調(diào)用了11次柱搜,
而自身調(diào)用了442次自身去計算之前計算過的值
因此我們可以用記憶的方式,來優(yōu)化一下程序
var fibonacciMemory = function () {
var meo = [0, 1];
var fib = function (n) {
var result = meo[n];
if(typeof result !== 'number') {
result = arguments.callee(n - 1) + arguments.callee(n - 2);
meo[n] = result;
}
return result;
}
return fib;
}();
var start = Date.now();
for(var i = 0; i <= 400; i++) {
if (i == 400) {
document.writeln("http:// " + i + " : " + fibonacciMemory(i) + "<br/>");
}
}
var end = Date.now();
document.writeln("記憶優(yōu)化時間: " + (end - start));
當(dāng)然漠酿,我們可以將記憶這種形式一般化
var memoizer = function (memo, fundamental) {
var shell = function (n) {
var result = memo[n];
if (typeof result !== 'number') {
result = fundamental(shell, n);
memo[n] = result;
}
return result;
}
return shell;
};
var fibonacci = memoizer([0, 1], function (shell, n) {
return shell(n - 1) + shell(n - 2);
});
alert(fibonacci(10)); // 55
alert(fibonacci(100)); // 354224848179262000000
var factorial = memoizer([1, 1], function (shell, n) {
return shell(n - 1) * n;
});
alert(factorial(5)); // 120
alert(factorial(50)); // 3.0414093201713376e+64