1. 程式人生 > 實用技巧 >Js閉包的實現原理和作用

Js閉包的實現原理和作用

閉包的實現原理和作用

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);
}