Js基礎知識6-JavaScript匿名函數和閉包
阿新 • • 發佈:2018-09-09
js基礎 訪問 fun null 個數 () nbsp 自我 每次
1,把匿名函數賦值給變量
var test = function() {
return ‘guoyu‘;
};
alert(test);//test是個函數
alert(test());
2,把匿名函數自我執行的返回值賦值給變量
var test = (function() {
return ‘GY‘;
})();
alert(test);//彈出 GY
3,自我執行,第一個圓括號放匿名函數,第二個括號執行並傳參
(function(a, b) {
alert(a+b);
})(2,5);//直接彈出7
4,自我執匿名函數的傳參
alert((function() {
return ‘guoyu‘;
})());
5,函數裏面放一個匿名函數
functiontest() {
return function() {
return ‘guoyu‘;
};
}
alert(test());//執行test(),結果是一個函數體
alert(test()());//彈出guoyu
var t = test();
alert(t());//彈出guoyu
閉包
閉包是指有權訪問另一個函數作用域中的變量的函數,創建閉包的常見方式,就是在一個函數內創建另一個函數,通過另一個函數訪問這個函數的局部變量
1,通過閉包可以返回局部變量
functiontest() {
var age = 28;
return function() {
return age;
};
}
alert(test()());//直接彈出 28
2,使用閉包有個優點,同時也是缺點:局部變量駐留內存中,可以避免使用全局變量(全局變量汙染導致應用程序的不可預知性,每個模塊都可以調用必將引來災難,推薦使用私有的,封裝的局部變量)
使用全局變量進行累加
var age = 20;
functiontest() {
age++;
return age;
}
alert(test());//21
alert(test());//22
如果你把var age = 20;放進test()函數內,那麽每次執行都會重新初始化為20,每次彈出的都是21,無論執行多少次!
3,使用匿名函數實現局部變量駐留內存中從而累加
functiontest() {
var age = 20;
return function() {
age++;
return age;
}
}
var t = test();
alert(t());//21
alert(t());//22
alert(t());//23
alert(t());//24
/*如果每次都初始化age = 20;那麽每次返回都是21,不能實現累加,因此要避免初始化那一句,只要調用第一個return 語句即可,每次只調用t()即可*/
t = null;//解除引用,等待垃圾回收
循環裏的匿名函數的取值問題
function test() {
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = function() {
return i;
};
}
//循環執行完畢,i最終是4++,就是5
return arr;
}
/*
alert(test());
打印出5個並列的“function() {return i;}”,
因為arr數組的每個元素都是一個匿名函數,每個匿名函數都是返回"i",
並不是返回1,2,3....,因為這個匿名函數是死的,沒有執行(自執行)
*/
alert(test()[0]);//彈出“function() {return i;}”
var t = test();
for (var i = 0; i < 5; i++) {
//alert(t[i]);//數組裏面都是一個沒有自執行的匿名函數
//現在讓數組裏的每個死函數執行起來,但是全都是彈出‘5’
//因為執行test()裏的循環後,i已經為5了,但每個數組裏面都存的是個死函數,返回一個死i
alert(t[i]());
}
如何解決上述的問題呢?
修改1
functiontest() {
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = i;//這裏不用匿名函數,直接給個i,
}
return arr;
}
var t = test();
for (var i = 0; i < 5; i++) {
alert(t[i]);//依次彈出0,1,2,3,4
}
修改2,通過自我即時執行匿名函數:
//將匿名函數裏面的變量駐留到內存感覺像全局變量
functiontest() {
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = (function(num) {
return num;
})(i);
}
return arr;
}
var t = test();
for (var i = 0; i < 5; i++) {
alert(t[i]);//依次彈出0,1,2,3,4
}
修改3:
functiontest() {
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = (function(num) {
//return num;
return function() {//這麽寫就是閉包了,閉包將變量駐留在內存,和前例中累加一個道理
return num;
};
})(i);
}
return arr;
}
var t = test();
for (var i = 0; i < 5; i++) {
//alert(t[i]);這裏返回的是5個依次“function() {return num;}”
alert(t[i]());//依次打印出0,1,2,3,4
}
閉包中的this
var test = {
getThis: function() {
return this;
}
};
alert(test.getThis());//[object Object]
再看看閉包中:
var test = {
getThis: function() {
return function() {//這麽寫就是閉包了
return this;
};
}
};
alert(test.getThis()());//[object Window]
結論:this 對象在運行時基於函數的執行環境綁定的,如果this在全局範圍就是widow,如果在對象內部就指向這個對象。而閉包在運行時指向window的,因為閉包不屬於這個對象的屬性或方法,再看下面
var user = ‘The Window‘;
var box = {
user:‘The Box‘,
getUser: function() {
//return this.user;
return function() {//這麽寫就是閉包了
return this.user;
};
}
};
alert(box.getUser()());//The Window
那麽有的同學想問了,怎麽才能讓它彈出 The box呢?
方法有兩個:對象冒充,變量保存_this
var user = ‘The Window‘;
var box = {
user:‘The Box‘,
getUser: function() {//這個地方要冒充一下
return function() {
return this.user;
};
}
};
alert(box.getUser().call(box));//The Box
var user = ‘The Window‘;
var box = {
user:‘The Box‘,
getUser: function() {
var _this = this;//保存到臨時變量
return function() {
return _this.user;
};
}
};
alert(box.getUser()());//The Box
模仿塊級作用域,for ,if 等塊級裏的東西封裝起來,變量私有化,可以保護數據,防止泄露,js沒有私有作用域這個概念
functiontest() {
for(var i = 0; i < 5; i++) {//塊級作用域,可惜JS沒這個東西
}
var i;//重新聲明也不影響
alert(i);//即使超出for塊級,依舊打印出5,說明js沒有塊級作用域這個概念
}
test();
開始使用塊級作用域,也就是出了if , for等塊,裏面的i就不再起效,方法就是包含自我執行的匿名函數,就可以實現私有作用域
functiontest() {
(function() {
for (var i = 0; i < 5; i++) {//包含自我執行的匿名函數,就可以實現私有作用域
alert(i);
}
})();
alert(i);
//這裏i就不認識了,相當於沒定義i,i被銷毀了,後面繼續定義i和上面的i沒任何關系,防止汙染
}
test();
(function() {
var age = 20;
alert(age);
})();
alert(age);//報錯,undefined
//這樣可以全局變量私有化,防止汙染
私有變量(外部不可訪問)
functiontest() {
var age = 20; //私有變量
}
functionTest() {
this.age = 20;//屬性:公有的,外部可訪問
this.run = function() {//方法:公有的
return ‘is running...‘;
};
}
var t = new Test();
alert(t.age);
alert(t.run());
functionTest() {
var age = 20; //私有變量
functionrun() {//私有函數
return ‘ is running...‘;
}
this.publicGo = function() { //對外可見的公共接口,特權方法
return age + run();
};
}
var t = new Test();
alert(t.publicGo());
//20 is running...私有變量,私有函數,通過公共接口被訪問
//把一些細節封裝起來,通過一些接口去訪問
Js基礎知識6-JavaScript匿名函數和閉包