閉包的實作原理和作用
1、閉包的概念:指有權訪問另一個函式作用域中的變數的函式,一般情況就是在一個函式中包含另一個函式,
2、閉包的作用:訪問函式內部變數、保持函式在環境中一直存在,不會被垃圾回識訓制處理
因為函式內部宣告 的變數是區域的,只能在函式內部訪問到,但是函式外部的變數是對函式內部可見的,這就是作用域鏈的特點了,
子級可以向父級查找變數,逐級查找,找到為止
1 function bar(){ 2 //外層函式宣告的變數 3 var value=https://www.cnblogs.com/xiaole9924/p/1; 4 5 function foo(){ 6 console.log(value); 7 } 8 return foo(); 9 }; 10 var bar2=bar; 11 //實際上bar()函式并沒有因為執行完就被垃圾回識訓制處理掉 12 //這就是閉包的作用,呼叫bar()函式,就會執行里面的foo函式,foo這時就會訪問到外層的變數 13 bar2();
因此我們可以在函式內部再創建一個函式,這樣對內部的函式來說,外層函式的變數都是可見的,然后我們就可以訪問到他的變數了,
3、閉包的優點:
- 方便呼叫背景關系中宣告的區域變數
- 邏輯緊密,可以在一個函式中再創建個函式,避免了傳參的問題
4、閉包的缺點:
因為使用閉包,可以使函式在執行完后不被銷毀,保留在記憶體中,如果大量使用閉包就會造成記憶體泄露,記憶體消耗很大
實際開發中JS閉包的應用
1,在函式外使用函式內的變數 .函式作為回傳值 (閉包作用:避免變數被環境污染)
1 function F1(){ 2 var a = 100; 3 return function(){ 4 console.log(a) 5 } 6 } 7 var f1 =F1(); 8 var a = 200; 9 f1()//100
1 function init(){ 2 var name = "hello world";//name是一個被init創建的區域變數 3 function sayName(){//sayName是一個內部函式,閉包 4 alert(name);//使用了父級函式宣告的變數name 5 } 6 sayName(); 7 } 8 init();//"hello world"
2.函式作為引數傳遞
1 function F1(){ 2 var a = 100; 3 return function(){ 4 console.log(a) 5 } 6 } 7 var f1 =F1(); 8 function F2(fn){ 9 var a = 200; 10 fn(); 11 } 12 F2(f1); // 100
3.將函式與其所操作的某些資料關聯起來,通常,你使用只有一個方法的物件的地方,都可以使用閉包
1 // 改變dom樣式 2 document.getElementById("a").onclick = setSize(12); 3 document.getElementById("b").onclick = setSize(18); 4 document.getElementById("c").onclick = setSize(22); 5 function setSize(fontSize){ 6 return function(){ 7 document.body.style.fontSize = fontSize + 'px'; 8 } 9 }
4.用閉包模擬私有方法
1 //這三個公共函式是共享同一個環境的閉包,多虧 JavaScript 的詞法作用域,它們都可以訪問 privateCounter 變數和 changeBy 函式, 2 var makeCounter = function () { 3 var privateCounter = 0; 4 function changeBy(val){ 5 privateCounter += val; 6 }; 7 return { 8 increment: function(){ 9 changeBy(1); 10 }, 11 decrement: function(){ 12 changeBy(-1); 13 }, 14 value: function(){ 15 return privateCounter; 16 } 17 } 18 }; 19 var Counter1 = makeCounter(); 20 var Counter2 = makeCounter(); 21 Counter1.increment(); 22 console.log(Counter1.value());//1 每次呼叫其中一個計數器時,通過改變這個變數的值,會改變這個閉包的詞法環境,然而在一個閉包內對變數的修改,不會影響到另外一個閉包中的變數, 23 console.log(Counter2.value());//0 以這種方式使用閉包,提供了許多與面向物件編程相關的好處 —— 特別是資料隱藏和封裝,
5.回圈里面的閉包
怎么才能實作輸出0-5呢?
1 for (var i = 0; i < 5; i++) { 2 setTimeout(function () { 3 console.log(i); 4 }, 1000 * i); 5 }//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) }
1 //使用let宣告變數 2 for (let i = 0; i < 5; i++) { 3 setTimeout(function () { 4 console.log(i); 5 }, 1000 * i); 6 }
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/174066.html
標籤:JavaScript
上一篇:NPM常用指令
