摘要:前提中閉包無處不在,你只需要能夠識別并擁有它。一實質(zhì)問題當函數(shù)可以記住并訪問所在的詞法作用域是,就產(chǎn)生了閉包。依然持有該作用域的引用。延遲函數(shù)的回調(diào)會在循環(huán)結(jié)束時才執(zhí)行。每個延遲函數(shù)都會講在每次迭代中創(chuàng)建的作用域封閉起來。
前提:JavaScript中閉包無處不在,你只需要能夠識別并擁有它。閉包是基于詞法作用域書寫代碼時自然產(chǎn)生的結(jié)果。
一、實質(zhì)問題當函數(shù)可以記住并訪問所在的詞法作用域是,就產(chǎn)生了閉包。有的人會很好奇,什么是詞法作用域,接下來我給大家普及一下什么是詞法作用域。
詞法作用域簡單的來說詞法作用域就是定義在詞法階段的作用域,換就話說,詞法作用域是由你在寫代碼時將變量和塊作用域?qū)懺谀睦飦頉Q定的
function foo(a){ var b = a*2; function bar(c){ console.log(a,b,c); } bar (b*3); } foo(2);
在這個例子中包含了三個逐級嵌套的作用域
1、包含整個全局作用域,foo
2、包含著foo所創(chuàng)建的作用域,a , bar , b
3、包含著bar所穿件的作用域 ,c
關(guān)于詞法作用域我們就現(xiàn)講這么多,接下來還是回到我們的正文,作用域閉包
function foo(){ var a=2; function bar(){//bar()的詞法作用域能夠訪問foo()的內(nèi)部作用域 console.log(a); } return bar;//將bar()函數(shù)當做一個值類型進行傳遞 } var baz =foo(); baz(2);
foo()內(nèi)部作用域依然存在,沒有被回收。bar()依然持有該作用域的引用。這個引用就叫閉包
function foo(){ var a=2; function baz(){ console.log(a); } bar(baz); } function bar(fn){ fn(); } foo(); //把內(nèi)部函數(shù)baz傳遞給bar, // 當調(diào)用這個內(nèi)部函數(shù), // 他涵蓋的foo()內(nèi)部作用域的閉包就可以觀察到了,因為它能夠訪問a
var fn; function foo(){ var a =2; function baz(){ console.log(a); }; fn = baz; } function bar(){ fn(); } foo(); bar();
無論通過何種手段將內(nèi)部函數(shù)傳遞到所在的詞法作用域以外,他都會持有對原始定義作用域的引用,無論在何處執(zhí)行這個函數(shù)都會使用閉包。
二、提升function wait(message){ setTimeout(function timer(){ console.log(message) },1000); }; wait("hello world");
在引擎內(nèi)部,內(nèi)置的工具函數(shù)setTimeout()持有對一個參數(shù)的引用,引擎會調(diào)用這個函數(shù),在這個例子中就是內(nèi)部的timer函數(shù),而詞法作用域就在這個過程中保持完整。這就是閉包。
三、循環(huán)和閉包for(var i=0;i<=5;i++){ setTimeout(function timer() { console.log(i); }, i*1000); } //大家猜猜結(jié)果會是啥?
正常情況下會分別輸出數(shù)字1~5,但實際會輸出五次6。
延遲函數(shù)的回調(diào)會在循環(huán)結(jié)束時才執(zhí)行??梢韵胂笠幌庐惒郊虞d機制。因此settimeout每次要等到循環(huán)結(jié)束后才顯示值,這樣就得到了我們的結(jié)果,輸出了五次6。
代碼中有什么缺陷導(dǎo)致它的行為通語義所暗示的不一致呢?
我們需要更多的作用域,特別是在循環(huán)的過程中每個迭代都要一個閉包作用域,因此想到了立即執(zhí)行函數(shù)
for( var i=0;i<=5;i++){ (function(){ setTimeout(function timer() { console.log(i); }, i*1000); })(); }
這樣子為什么還不行呢?我們顯然擁有了更過的詞法作用域。
每個延遲函數(shù)都會講IIFE在每次迭代中創(chuàng)建的作用域封閉起來。
如果作用域是空的話,我們的IIE只是一個什么都沒用的空作用域。
for( var i=1;i<=5;i++){ (function(){ var j =i; setTimeout(function timer() { console.log(j); }, j*1000); })(); }重返塊作用域
for(let i =1;i<=5;i++){ setTimeout(function timer() { console.log(i); }, i*1000); }
let欺騙此法作用域,每次在迭代都去創(chuàng)建一個新的作用域,然后執(zhí)行完后被銷毀,這樣每個迭代都有自己的作用域就可以達到我們的預(yù)期效果,輸出1~5。
四、模塊function coolModule(){ var something = "cool"; var another = [1,2,3]; function doSomething(){ console.log(something); } function doAnother(){ console.log(another.join("!")); } return { doSomething: doSomething, doAnother: doAnother }; } var foo = coolModule(); foo.doAnother(); foo.doSomething();
這個模式JavaScript中被稱為模塊,保護私有屬性,只提供公共方法。
模塊模式需要具備兩個必要條件:
1、必須有外部的封閉函數(shù)
2、封閉函數(shù)必須返回至少一個內(nèi)部函數(shù)
現(xiàn)代的模塊機制大多數(shù)模塊依賴加載器/管理器本質(zhì)上都是將這種模塊定義封裝進一個友好的API。
var MyModules = (function Manager(){ var modules = {}; function define(name,deps,impl){ for(var i=0;i
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/107700.html
摘要:通過可取可取的他們所屬對象的上下文的方法稱為公共方法函數(shù)調(diào)用模式當一個函數(shù)并非一個對象的屬性時,那么它就是被當做一個函數(shù)來調(diào)用的,以此模式調(diào)用函數(shù),被綁定到了全局對象。 前言: 前端這兩年的新技術(shù)鋪天蓋地,各種框架、工具層出不窮眼花繚亂。最近打算好好復(fù)習(xí)下 js 基礎(chǔ),夯實的基礎(chǔ)才是學(xué)習(xí)新技術(shù)的基石。本文作為讀書筆記簡單的總結(jié)下 js 函數(shù)的基礎(chǔ)知識。 一、函數(shù)對象 JavaScr...
摘要:本期推薦文章從作用域鏈談閉包,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。推薦理由這是一篇譯文,深入淺出圖解作用域鏈,一步步深入介紹閉包。作用域鏈的頂端是全局對象,在全局環(huán)境中定義的變量就會綁定到全局對象中。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周開始前端進階的第二期,本周的主題是作用域閉包,今天是第6天。 本...
摘要:閉包面試題解由于作用域鏈機制的影響,閉包只能取得內(nèi)部函數(shù)的最后一個值,這引起的一個副作用就是如果內(nèi)部函數(shù)在一個循環(huán)中,那么變量的值始終為最后一個值。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進階的第二期,本周的主題是作用域閉包,今天是第8天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了...
摘要:下面我們就羅列閉包的幾個常見問題,從回答問題的角度來理解和定義你們心中的閉包。函數(shù)可以通過作用域鏈相互關(guān)聯(lián)起來,函數(shù)內(nèi)部的變量可以保存在其他函數(shù)作用域內(nèi),這種特性在計算機科學(xué)文獻中稱為閉包。 寫這篇文章之前,我對閉包的概念及原理模糊不清,一直以來都是以通俗的外層函數(shù)包裹內(nèi)層....來欺騙自己。并沒有說這種說法的對與錯,我只是不想擁有從眾心理或者也可以說如果我們說出更好更低層的東西,逼格...
摘要:理解的函數(shù)基礎(chǔ)要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統(tǒng)的類繼承還要強大。中文指南基本操作指南二繼續(xù)熟悉的幾對方法,包括,,。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家?guī)韼椭?...(據(jù)說是阿里的前端妹子寫的) this 的值到底...
閱讀 749·2021-10-09 09:44
閱讀 2029·2021-09-22 15:54
閱讀 5065·2021-09-22 10:55
閱讀 1448·2019-08-29 18:41
閱讀 784·2019-08-29 11:24
閱讀 2110·2019-08-28 18:20
閱讀 1035·2019-08-26 11:51
閱讀 3055·2019-08-26 11:00