1. 程式人生 > >JavaScript 經典之一 閉包

JavaScript 經典之一 閉包

如果 空字符串 domo 然而 logs bsp 學習 相同 com

作為一個前端開發者,閉包是必須要攻克掉的障礙。據說好多面試者掛在閉包面試上。下面我就給大家講一下我理解中的閉包。不說太多的廢話,直接進入主題。

變量作用域

學習編程語言需要明白,變量的作用域。變量作用域分全局變量、局部變量。全局變量盡量少用,因為它很耗費性能。簡單理解,全局變量:在任何一個地方都可以訪問到。局部變量只有在局部才可以訪問到。先舉個例子看看:

var data=100;
function domo(){
    var data1=20;
    console.log(data);
    console.log(data1);
}
domo();

技術分享

可以看出data在dome中也可被訪問。所有呢!data是全局變量,data1是局部變量。

閉包

1.常見閉包

/**
 * 最簡單的閉包
 * */
function bibao(){
    var d=10;
    return function(){
        console.log(d);
        d++;
    }
}
var _bibao=bibao();
_bibao();//輸出10
_bibao();//輸出11

首先我們要明白函數是有返回值的,如果不手動更改返回值則返回undefined。如何手動更改返回值?就是在函數中使用return 返回。可以返回為布爾值也可以是對象也可以是空字符串也可以是函數。這個最簡單的閉包就是返回一個匿名函數。_bibao接收到bibao函數的返回。相當於_bibao===function(){console.log(d);d++;

}。然而這個匿名函數中用到了d。此刻_bibao就可以訪問d;也可以更改d

2.無return閉包

  1. /**
     * 無return的閉包
     * 
     * */
    var _bibao1;
    function bibao1(){
        var d=20;
        _bibao1= function(){
            console.log(d);
            d++;
        }
    }
    bibao1();
    _bibao1();//輸出20
    _bibao1();//輸出21
    
    
    

這種沒有return 的閉包其實跟上面最簡單的閉包是相同的,它只不過把一個匿名函數賦值給全局變量。全局變量此刻保持對這個匿名函數的引用。當調用_bibao1()的時候,就等於調用這個匿名函數。

3.回掉函數中產生的閉包

/**
 * 回掉函數中產生的閉包
 * @callback {Function} 回掉函數
 * */

function bibao2(callback){
    var d=100;
    setTimeout(function(){
        callback()
    },2000)
}

function _bibao2(){
    var d=120;
    bibao2(function(){
        console.log(d);
        d++;
    });
    setTimeout(function(){
        console.log(d);
    },3000)
}
_bibao2();//兩秒後輸出120。三秒後輸出121

只有記住一個變量或者參數是一個函數的引用,這個答案就會迎刃而解。執行_bibao2();它會執行bibao2,然後傳入一個匿名函數,此刻這個匿名函數保持可以訪問到_bibao2中的d。bibao2中的參數callback保持對這個匿名函數的引用。所以它訪問的是_bibao2中的d而不是bibao2中的d。

總結

閉包是很有用的,也是很常用的,只有我們記住了它的原理,就能夠掌控它們。它只不過是一個函數的引用,這個函數可以訪問到這個函數的父函數中的變量而已。

JavaScript 經典之一 閉包