av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

一段代碼帶你論證JS基礎(chǔ)[不看后悔篇]

前言

JS基礎(chǔ)對(duì)于我們前端開(kāi)發(fā)的重要性不言而知~于是,我們都會(huì)選擇去閱讀一些書(shū)籍來(lái)充實(shí)自己。那當(dāng)我們讀完那些理論基礎(chǔ)之后,你是否依舊迷茫,還是豁然開(kāi)朗?

透過(guò)現(xiàn)象看本質(zhì)!

我想:有了理論基礎(chǔ)作為根據(jù)的時(shí)候,應(yīng)該多去思考一些代碼的結(jié)果來(lái)實(shí)踐這些理論。

就比如解決bug一樣,你總得先知道出現(xiàn)bug的原因,再根據(jù)原因去解決問(wèn)題是一樣的道理。

code案例

 
 
 
 
  1. var b = 10; 
  2. (function b(){ 
  3.     b = 20; 
  4.     console.log(b);  
  5. })(); 

這段代碼會(huì)輸出什么呢?

(ps:先別著急回答,好好思考一下)

乍一看,這段代碼很簡(jiǎn)單,涉及到的內(nèi)容是var function IIFE,好像也沒(méi)什么問(wèn)題。

這段代碼的在嚴(yán)格模式下輸出:TypeError: Assignment to constant variable

意思就是:類(lèi)型錯(cuò)誤:對(duì)常量變量的賦值

而在非嚴(yán)格模式下輸出:

輸出分析

分析嚴(yán)格模式下的輸出如果由這個(gè)TypeError: Assignment to constant variable.做一個(gè)分析的話,那么意味著變量b是不可修改的!

那么現(xiàn)在的問(wèn)題在于變量b是指外部用var聲明的變量b呢,還是立即執(zhí)行的具名函數(shù)b呢?

如果b是立即執(zhí)行的具名函數(shù)名稱,說(shuō)實(shí)話我也不大確定它是否是可修改。

(ps:大多數(shù)的js書(shū)籍中都沒(méi)有明確指出立即執(zhí)行函數(shù)表達(dá)式是否能重新賦值的問(wèn)題)

但是我一定可以確定的是,如果b是指外部用var聲明的,那么在此代碼中它一定是可修改的。我們都知道用var聲明的全局變量它在任何地方肯定是可以修改的,因?yàn)樵撟兞刻幱谧饔糜虻淖铐敹恕?/p>

所以在這里我想大膽做個(gè)假設(shè):變量b是指立即執(zhí)行的具名函數(shù)名稱b~

做完這個(gè)假設(shè),我想說(shuō):

那意味著全局變量b在立即執(zhí)行的具名函數(shù)b里訪問(wèn)不到嗎?

其實(shí)不是的,全局變量b在立即執(zhí)行的具名函數(shù)b是可被訪問(wèn)的,只不過(guò)因?yàn)榫呙瘮?shù)b的內(nèi)部作用域里也存在了一個(gè)用function聲明的變量b,所以在代碼執(zhí)行的時(shí)候js引擎首先找到用function聲明的變量b。正如書(shū)籍中講到的作用域查詢是通過(guò)從里到外向上查詢。

(ps:之前也順手寫(xiě)了一篇關(guān)于作用域系列的文章:我是這樣理解JavaScript中作用域,望能幫助大家~)

當(dāng)然在非嚴(yán)格模式下,大家可以試著動(dòng)手在立即執(zhí)行的具名函數(shù)內(nèi)部函數(shù)打印一下window.b,也可論證全局變量b在立即執(zhí)行的具名函數(shù)b里可被訪問(wèn)!代碼如下:

 
 
 
 
  1. var b = 10; 
  2. (function b(){ 
  3.     b = 20; 
  4.     console.log(window.b);  
  5. })(); 

到這里,理清楚了立即執(zhí)行函數(shù)b的內(nèi)部作用域機(jī)制,我的疑問(wèn)又萌生了:

為什么(function b(){}())這樣的函數(shù)表達(dá)式就不能修改呢?

后來(lái),我查閱了資料,明白了IIFE函數(shù)的內(nèi)部機(jī)制~

我所理解的是:

當(dāng)遇到具名的函數(shù)表達(dá)式的時(shí),會(huì)創(chuàng)建一個(gè)輔助的特定對(duì)象,將函數(shù)表達(dá)式的名稱作為唯一的key,用來(lái)存儲(chǔ)函數(shù)表達(dá)式的名稱,然后添加到函數(shù)的作用域鏈中,該值只讀,并且不可以被刪除,所以不能對(duì)該值進(jìn)行操作。

所以,在嚴(yán)格模式下,一個(gè)不可修改的常量被修改之后就會(huì)報(bào)TypeError: Assignment to constant variable。

分析非嚴(yán)格模式的輸出 在非嚴(yán)格模式下會(huì)靜默失敗,所以不報(bào)錯(cuò)。針對(duì)如上的分析之后,會(huì)輸出立即執(zhí)行的具名函數(shù)b本身。

code擴(kuò)展

我將代碼改寫(xiě)成:

 
 
 
 
  1. var b = 10; 
  2. (function b(){ 
  3.  return 1; 
  4. })(); 
  5. console.log(b);  

那這段又會(huì)輸出什么呢?

無(wú)論在非嚴(yán)格模式還是在嚴(yán)格模式下,這段代碼都會(huì)輸出10,也就是全局變量b的值~

寫(xiě)這段代碼的本意并不是為了猜測(cè)結(jié)果而想的,我想表達(dá)的是:為什么立即執(zhí)行具名函數(shù)b在外部是不可訪問(wèn)的?難道所有的表達(dá)式在外部都不可訪問(wèn)嗎?

為了解決我的疑問(wèn),我通過(guò)如下函數(shù)foo1和foo2進(jìn)行分析:

 
 
 
 
  1. ///片段1 
  2. var foo1 = function () {}; 
  3. console.log(foo1); 
  4. //片段2 
  5. (function foo2(){}) 
  6. console.log(foo2); 

片段1

是讓一個(gè)匿名函數(shù)表達(dá)式賦值給變量foo1,然后該函數(shù)可以用foo1這個(gè)名稱進(jìn)行訪問(wèn)——foo1()。所以打印是一個(gè)函數(shù)。

片段2

是一個(gè)函數(shù)表達(dá)式,但結(jié)果是Uncaught ReferenceError: foo2 is not defined。說(shuō)明在外部是不可訪問(wèn)的。

可見(jiàn),立即執(zhí)行具名函數(shù)b是一個(gè)函數(shù)表達(dá)式,在外部是不可訪問(wèn)的!(ps:意味著函數(shù)表達(dá)式既不可能通過(guò)名稱在函數(shù)聲明之前調(diào)用它,也不可能在聲明之后調(diào)用它)。

其實(shí),大多數(shù)書(shū)籍里介紹以及我之前所理解的片段1這樣的代碼就是一個(gè)函數(shù)表達(dá)式。但現(xiàn)在我的理解并不是這樣的~

foo1是一個(gè)變量,匿名函數(shù)表達(dá)式賦值給變量foo1了,所以foo1它可被訪問(wèn)!

通過(guò)自己寫(xiě)了2個(gè)代碼片段,將我的疑惑迎刃而解了~

思考其他案例

在閑暇之余,我將最原始的代碼塊再做了改造,運(yùn)用這些代碼來(lái)溫故并且思考了之前學(xué)習(xí)的理論基礎(chǔ)。

如下的代碼片段,我將結(jié)果也一并和大家揭曉,但我也會(huì)和大家分享一下我的心得~

 
 
 
 
  1. ///片段1 
  2. var b = 10; 
  3. function b() { 
  4.  console.log(12); 
  5.  return 1; 
  6. console.log(b, b());  
  7. //10 TypeError: b is not a function 

為什么會(huì)打印10呢,而不是函數(shù)b呢?

論據(jù):函數(shù)聲明優(yōu)先于變量聲明~

所以,相當(dāng)于先利用function聲明了函數(shù)b,再利用var重寫(xiě)了b。

 
 
 
 
  1. //片段2 
  2. console.log(b, b()); //12 1 
  3. var b = 10; 
  4. function b() { 
  5.  console.log(12); 
  6.  return 1; 

為什么會(huì)打印函數(shù)b的執(zhí)行結(jié)果12和1呢,而不是全局變量b呢?

論據(jù):函數(shù)聲明優(yōu)先于變量聲明~并且在這個(gè)過(guò)程中存在變量提升。

片段3

 
 
 
 
  1. var b = 10; 
  2. b = function() { 
  3.  b = 20; 
  4.  console.log(b); //20 
  5. return 1; 
  6. }; 
  7. console.log(b, b()); //b函數(shù),1 

為什么會(huì)打印10呢,而不是函數(shù)b呢?

論據(jù):這個(gè)過(guò)程就是將變量b進(jìn)行重新賦值。

所以,打印的是10,而不是函數(shù)。

片段4

 
 
 
 
  1. var b = 10; 
  2. //  Duplicate declaration "b" 
  3. let b = function() { 
  4.  b = 20; 
  5.  console.log(b); 
  6.  return 1; 
  7. }; 

論據(jù):用var聲明變量可以可重復(fù)聲明,但是用let聲明變量不可重復(fù)聲明。

所以js引擎要執(zhí)行完var b = 10語(yǔ)句之后,遇到了let b之前報(bào)錯(cuò)了。

總結(jié)

在寫(xiě)業(yè)務(wù)代碼的時(shí)候,要盡量去避免聲明變量命名沖突的情況,因?yàn)橐陨习咐牡膶?xiě)法是不合理的,很容易出現(xiàn)意想不到的結(jié)果。

為何不規(guī)范要求自己而避開(kāi)不必要的麻煩呢?

當(dāng)然,我覺(jué)得在學(xué)習(xí)乏味難啃的理論基礎(chǔ)知識(shí)時(shí),我覺(jué)得應(yīng)該創(chuàng)造自己的想象力,多去實(shí)踐多去思考為什么會(huì)有這樣的結(jié)果呢?

根據(jù)理論證實(shí)結(jié)果!

這樣才會(huì)使得讓自己更加理解理論基礎(chǔ),并且更好的運(yùn)用它們,而不僅僅是背/記。

原文:juejin.cn/user/2189882895108616

本文轉(zhuǎn)載自微信公眾號(hào)「前端人」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系前端人公眾號(hào)。


當(dāng)前文章:一段代碼帶你論證JS基礎(chǔ)[不看后悔篇]
瀏覽路徑:http://uogjgqi.cn/article/coioheg.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們?cè)谖⑿派?4小時(shí)期待你的聲音

解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流