一. 匿名函數
1. 函數的定義,可分爲三種
1) 函數聲明方式html
function
double(x) {
return 2*x;
}
2)Function構造函數,把參數列表和函數體都做爲字符串,不方便,不建議使用安全
var
double =
new Function('x', 'return 2*x;');
3)函數表達式方式閉包
var
double = function(x) {
return 2*x;
}
該形式中,等號右邊是一個匿名函數,建立函數完畢後,將該函數賦給了變量double。函數
2. 匿名函數
1)第一種方式this
var double= function(x) {
return 2*x;
}
等號右邊是一個匿名函數。注意匿名函數不能直接獨立的房子代碼中,以下代碼spa
functino(x) {
return 2*x;
}
//
SyntaxError: Unexpected token (
2)第二種方式code
(
function(x,y) {
console.log(x+y);
})(2,3);
建立一個匿名函數(在第一個括號內),第二個括號用於調用該匿名函數並傳入參數。htm
二. 閉包(Closure)
閉包的含義:外層函數包含內層函數,內層函數能夠訪問外層函數的全部變量,即便外層函數執行完畢。(JavaScript做用域鏈)blog
題外話:上述對於閉包的解釋與《JavaScript 閉包系列一》中不徹底吻合。 上述解釋,閉包成立只需知足:函數inner嵌套在函數outer內部。另外一些文章對於閉包的解釋,閉包成立須要兩個條件:1)函數inner嵌套在函數outer內部;2)函數outer返回函數inner。對此,我已經凌亂了,各路大俠誰可以給個定論?token
Example 1:
函數outer是瞬間執行的(約0.00001毫秒),在函數outer體內建立了一個變量str,在outer執行完畢後,str變量未被釋放,這是因爲setTimeout內的匿名函數存在對變量str的引用。等到2秒後,匿名函數執行完畢,str才被釋放。
function outer() {
var str = "closure";
setTimeout(
function() {
console.log(str);
}, 2000);
}
outer();
//
closure
Example 2:此例是否爲閉包呢?
function outer() {
var i = 22;
(
function inner() {
console.log(i);
})();
}
outer();
//
22
Example 3:簡化代碼
function forTimeout(x, y) {
console.log(x + y);
}
function delay(x, y, time) {
setTimeout('forTimeout(' + x + ',' + y + ')', time);
}
//
簡化後
function delay(x, y, time) {
setTimeout(
function() {
forTimeout(x,y);
}
,time);
}
delay(3, 4, 2000);
//
7
三. 匿名函數與閉包
匿名函數的最大用途是建立閉包,它也可用來構建命名空間,減小全局變量的使用。
Example1:
匿名函數中的addEvent和removeEvent爲局部變量,可是能夠經過全局變量oEvent使用它,大大減小了全局變量的使用,加強了網頁的安全性。
var oEvent = {};
(
function() {
var addEvent =
function() {};
function removeEvent(){}
oEvent.addEvent = addEvent;
oEvent.removeEvent = removeEvent;
})();
Example2:
建立一個變量sun_mile_rain,並經過直接調用匿名函數初始化爲5,這種小技巧有時十分有用。
var sun_mile_rain = (
function(x , y){
return x + y;
})(2 , 3);
console.log(sun_mile_rain);
//
5
//
也可以使用以下的方式,第一個括號只是幫助咱們閱讀,可是不推薦下面這種書寫格式
var sun_mile_rain =
function(x , y){
return x + y;
}(2 , 3);
Example3:
代碼中,變量one定義在函數內部,是一個局部變量,所以外部是不能夠訪問的。但inner函數能夠訪問變量one,又將全局變量outer引用了inner,所以執行outer()能訪問到one的值。
var outer =
null;
(
function() {
var one = 1;
function inner() {
one += 1;
console.log(one);
}
outer = inner;
})();
outer();
//
2
outer();
//
3
outer();
//
4
換一種形式:函數fn執行,返回inner,將fn的執行結果賦給全局變量outer。執行outer也能訪問到one的值。所以可得知閉包的形式能夠有多種。
function fn() {
var one = 1;
function inner() {
one += 1;
console.log(one);
}
return inner;
}
var outer = fn();
outer();
//
2
outer();
//
3
outer();
//
4
四. 閉包與變量
閉包容許內層函數引用父函數中的變量,但該變量是最終值。
鼠標移過每個li元素時,控制檯輸出的值都是3,而不是咱們指望的元素下標。當mouseover事件調用監聽函數時,首先在匿名函數內部查找i是否認義,結果沒找到,所以向上查找,在全局環境中找到i,而且i的值是3(循環後的值)。所以每次輸出的都是3。
/*
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
*/
var lists = document.getElementsByTagName("li");
for(
var i=0; i<lists.length; i++) {
lists[i].onmouseover =
function() {
console.log(i);
}
}
注意:此處的閉包,並非函數嵌套函數的形式,而是匿名函數包含在全局環境中的形式。
針對上述代碼,有三種方法改進,使得鼠標移動到li元素上時,控制檯輸出對應的下標值。
1)當即執行的匿名函數
var lists = document.getElementsByTagName("li");
for (
var i = 0; i < lists.length; i++) {
(
function(index) {
lists[i].onmouseover =
function() {
console.log(index);
};
})(i);
}
2)在DOM元素上綁定$$index屬性記錄下標
var lists = document.getElementsByTagName("li");
for (
var i = 0; i < lists.length; i++) {
lists[i].$$index = i;
lists[i].onmouseover =
function() {
console.log(
this.$$index);
};
}
3)
var lists = document.getElementsByTagName("li");
for (
var i = 0; i < lists.length; i++) {
eventListener(lists[i],i);
}
function eventListener(list,index) {
list.onmouseover =
function() {
console.log(index);
}
}
時間:2014-10-23
地點:合肥
引用:http://www.cnblogs.com/rainman/archive/2009/05/04/1448899.html