Js閉包的實現原理和作用
阿新 • • 發佈:2020-12-07
閉包的實現原理和作用
1、閉包的概念:指有權訪問另一個函式作用域中的變數的函式,一般情況就是在一個函式中包含另一個函式。
2、閉包的作用:訪問函式內部變數、保持函式在環境中一直存在,不會被垃圾回收機制處理
因為函式內部宣告 的變數是區域性的,只能在函式內部訪問到,但是函式外部的變數是對函式內部可見的,這就是作用域鏈的特點了。
子級可以向父級查詢變數,逐級查詢,找到為止
function bar(){
//外層函式宣告的變數
var value=1;
function foo(){
console.log(value);
}
return foo();
};
var bar2=bar;
//實際上bar()函式並沒有因為執行完就被垃圾回收機制處理掉
//這就是閉包的作用,呼叫bar()函式,就會執行裡面的foo函式,foo這時就會訪問到外層的變數
bar2();
因此我們可以在函式內部再建立一個函式,這樣對內部的函式來說,外層函式的變數都是可見的,然後我們就可以訪問到他的變量了。
3、閉包的優點:
- 方便呼叫上下文中宣告的區域性變數
- 邏輯緊密,可以在一個函式中再建立個函式,避免了傳參的問題
4、閉包的缺點:
因為使用閉包,可以使函式在執行完後不被銷燬,保留在記憶體中,如果大量使用閉包就會造成記憶體洩露,記憶體消耗很大
實際開發中js閉包的應用
1。在函式外使用函式內的變數 .函式作為返回值 (閉包作用:避免變數被環境汙染)
function F1(){
var a = 100;
return function(){
console.log(a)
}
}
var f1 =F1();
var a = 200;
f1()//100
function init(){
var name = "hello world";//name是一個被init建立的區域性變數
function sayName(){//sayName是一個內部函式,閉包
alert(name);//使用了父級函式宣告的變數name
}
sayName();
}
init();//"hello world"
2.函式作為引數傳遞
function F1(){
var a = 100;
return function(){
console.log(a)
}
}
var f1 =F1();
function F2(fn){
var a = 200;
fn();
}
F2(f1); // 100
3.將函式與其所操作的某些資料關聯起來,通常,你使用只有一個方法的物件的地方,都可以使用閉包
// 改變dom樣式
document.getElementById("a").onclick = setSize(12);
document.getElementById("b").onclick = setSize(18);
document.getElementById("c").onclick = setSize(22);
function setSize(fontSize){
return function(){
document.body.style.fontSize = fontSize + 'px';
}
}
4.用閉包模擬私有方法
//這三個公共函式是共享同一個環境的閉包。多虧 JavaScript 的詞法作用域,它們都可以訪問 privateCounter 變數和 changeBy 函式。
var makeCounter = function () {
var privateCounter = 0;
function changeBy(val){
privateCounter += val;
};
return {
increment: function(){
changeBy(1);
},
decrement: function(){
changeBy(-1);
},
value: function(){
return privateCounter;
}
}
};
var Counter1 = makeCounter();
var Counter2 = makeCounter();
Counter1.increment();
console.log(Counter1.value());//1 每次呼叫其中一個計數器時,通過改變這個變數的值,會改變這個閉包的詞法環境。然而在一個閉包內對變數的修改,不會影響到另外一個閉包中的變數。
console.log(Counter2.value());//0 以這種方式使用閉包,提供了許多與面向物件程式設計相關的好處 —— 特別是資料隱藏和封裝。
資源搜尋網站大全 https://www.renrenfan.com.cn 廣州VI設計公司https://www.houdianzi.com
5.迴圈裡面的閉包
怎麼才能實現輸出0-5呢?
for (var i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, 1000 * i);
}//55555
//方法一,makeCallback函式為每一個回撥建立一個新的詞法環境。
function makeCallback(i) {
return function() {
console.log(i)
};
}
for(var i=0;i<10;i++){
setTimeout(makeCallback(i),1000)
}
//另一種方法使用了匿名閉包
for(var i=0;i<10;i++){
(function(i){
setTimeout(function () {
console.log(i)
},1000)
})(i)
}
//使用let宣告變數
for (let i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, 1000 * i);
}