從新認識閉包

閉包這個概念做爲前端來講算是耳熟能詳了,基本是面試的時候必問的問題,基本上隨便找個前端都能說出點什麼。 閉包指的是:可以訪問另外一個函數做用域的變量的函數。清晰的講:閉包就是一個函數,這個函數可以訪問其餘函數的做用域中的變量 例以下面這個例子eg1:前端

function A() {
    var b = 1
    function C() {
        console.log(b) // 函數C就是一個閉包
        return b++
    }
    return C
}
複製代碼

一般咱們面試的時候都會給這麼一個例子。 以前面試的人還給咱們寫出了這麼一個例子eg2:es6

var b = 1
function A() {
    console.log(b)
    return b++
}
複製代碼

我當時直接就否認了他,說這不是。直到今晚我又一次讀高程的時候,裏面也寫到了這麼一個例子,我頓時感到一陣後怕,立刻又看了一下閉包的概念。書中說到:該函數能使用函數外定義的變量,那麼咱們來看上面的那個例子不正是這樣子的嗎?頓時一頓汗顏。那麼咱們來講說閉包的使用場景和優缺點吧。面試

1.優勢

1.從外部訪問函數的變量閉包

經過上eg1能夠看出咱們執行A()的時候會給咱們返回函數C而且攜帶了變量b,這能爲咱們作什麼事情呢?看下面一個例子eg3:
複製代碼
function create_counter(initial) {
    var x = initial || 0
    return {
        function inc() {
            x += 1
            return x
        }
    }
}
var c1 = create_counter()
c1.inc() // 1
c1.inc() // 2
c1.inc() // 3
var c2 = create_counter(10)
c2.inc() // 11
複製代碼

2.模擬塊級做用域 eg4:函數

function count() {
    var arr = []
    for (var i=1; i<=3; i++) {
        arr.push(function () {
            return i * i
        });
    }
    return arr
}

var c1 = count()
var f1 = c1[0]
var f2 = c1[1]
var f3 = c1[2]
複製代碼

看上面的代碼咱們也許會想到返回的arr是三個函數分別是ui

c1 = [function() {return 11}, function() {return 22}, function() {return 3*3}] 依次調用f1,f2,f3會獲得1,4,9,可是結果都是16 緣由就在於返回的函數引用了變量i,但它並不是馬上執行。等到3個函數都返回時,它們所引用的變量i已經變成了4,所以最終結果爲16。 那麼按照閉包的定義咱們對以上代碼作修改 eg5:this

function count() {
    var arr = []
    for (var i=1; i<=3; i++) {
        arr.push((function (n) {
            return n * n
        })(i));
    }
    return arr
}
var c1 = count()
var f1 = c1[0]
var f2 = c1[1]
var f3 = c1[2]
複製代碼

這裏使用了匿名函數的自調用,在函數內部使用就是一個閉包,由於它能反問外部函數的任何變量。如今再執行就會獲得1,4,9 固然有了es6的let後已經不須要這麼麻煩了。spa

缺點

1.this的指向問題code

eg6:內存

var INFO = {
    name: '哈哈哈',
    sayName: function () {
        return function () {
            console.log(this.name)
        }
    }
}
複製代碼

由於這裏的執行環境是window了因此這裏的this指向不是INFO了。

2.內存泄露問題 eg7:

function test() {
    var a = 1
    function innerFunc () {
        console.log(a)
    }
    return innerFunc
}
var f1 = test()
f1() // 1
複製代碼

按照js的回收機制是執行完就回收,那麼執行完test 變量就應該被回收了,可是沒有,由於返回的innerFunc中使用了變量a,因此test不能被回收,如何避免呢,那就是執行完之後手動清除。

菜雞一個,有錯誤請指出。

相關文章
相關標籤/搜索