hello,闭包
定義
當(dāng)函數(shù)可以記住并訪問它定義時候的作用域,就產(chǎn)生了閉包。也就是說,一個函數(shù)在另外一個函數(shù)里面定義,但是它執(zhí)行的時候,可能是在其他的作用域,但是它還是能夠憑著出生時的回憶,找到定義時的作用域,去訪問里面的變量。
function foo() {var a = 2;function bar() {console.log(a)}return bar;}var bar = foo();bar();//記住了定義時的作用域,所以還是可以訪問到a,這里會輸出2為什么能夠訪問到定義時候的作用域呢?答案只有一個,定義閉包的函數(shù)是個重情義的家伙,考慮到那個寶寶可能隨時要用到它里面的變量,都不肯被回收。沒錯,這樣會導(dǎo)致foo的作用域一直沒有被回收,有一點浪費內(nèi)存空間。
關(guān)于this對象
一般函數(shù)的this指向的是調(diào)用它的對象。由于閉包函數(shù)是由window調(diào)用的,所以一般它的this指向window。如果你需要讓它指向某個對象,可以用call或者把外部的this保存起來,在里面直接使用。
var name = 'window';var object = {name: 'My Object',//var that = this;getNameFunc: function() {return function() {console.log(this.name);//console.log(that.name);}}}object.getNameFunc()();//輸出'window'object.getNameFunc().call(object);//輸出'My Object'循環(huán)和閉包
很常見的一段代碼,運行結(jié)果就是輸出5個5。因為這里的i沒有塊級作用域,也就是說閉包里面的函數(shù)訪問到外部的變量i只有一個,加上setTimeout是異步的,執(zhí)行到里面的回調(diào)的時候,外面的這個i的值就是循環(huán)結(jié)束后的值5。
for(var i = 0; i < 5; i++) {setTimeout(function() {console.log(i);}, 1000)}在沒有l(wèi)et的時候,我們都是通過模仿塊級作用域來解決。這個時候,閉包函數(shù)定義的作用域變成了(function(){}),然后在這個作用域里面把i的值賦值給j,每個閉包函數(shù)訪問到的j就是它定義時候作用域已經(jīng)保存好了的,自然就能夠正確的輸出。
for(var i = 0; i < 5; i++) {(function() {var j = i;setTimeout(function() {//閉包console.log(j);}, 1000)})()}當(dāng)然,我們一般都舍不得再用一個j來保存,直接用傳參數(shù)的形式,讓塊級作用域可以訪問到i的值。
for(var i = 0; i < 5; i++) {(function(j) {setTimeout(function() {//閉包console.log(j);}, 1000)})(i)}簡單改一下,每次用個塊級作用域的let來保存一下是不是就可以了啊
for(var i = 0; i < 5; i++) {let j = i;setTimeout(function() {console.log(j);}, 1000)}哈哈哈,真的就輸出0 1 2 3 4 5了。因為閉包記住了它定義時候的作用域呀,這個時候的j是塊級的,能夠好好地保存起來被閉包函數(shù)使用。
其實就是相當(dāng)于每次循環(huán)都會去聲明一個j,然后這個j的作用域就屬于這次循環(huán),所以可以直接把j的賦值寫在for循環(huán)里。
模塊化
可以使用閉包來實現(xiàn)模塊化的。
var module = (function(window) {function test1() {}functon test2() {}return {test1: test1,test2: test2}})(window)總結(jié)
- 上一篇: win10 git bash 闪退
- 下一篇: Vue3路由进阶实战:深度解析参数传递与