成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

開發 前端
JS基礎對于我們前端開發的重要性不言而知~于是,我們都會選擇去閱讀一些書籍來充實自己。那當我們讀完那些理論基礎之后,你是否依舊迷茫,還是豁然開朗?

 [[357950]]

前言

JS基礎對于我們前端開發的重要性不言而知~于是,我們都會選擇去閱讀一些書籍來充實自己。那當我們讀完那些理論基礎之后,你是否依舊迷茫,還是豁然開朗?

透過現象看本質!

我想:有了理論基礎作為根據的時候,應該多去思考一些代碼的結果來實踐這些理論。

就比如解決bug一樣,你總得先知道出現bug的原因,再根據原因去解決問題是一樣的道理。

code案例

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

這段代碼會輸出什么呢?

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

乍一看,這段代碼很簡單,涉及到的內容是var function IIFE,好像也沒什么問題。

這段代碼的在嚴格模式下輸出:TypeError: Assignment to constant variable

意思就是:類型錯誤:對常量變量的賦值

而在非嚴格模式下輸出:

輸出分析

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

那么現在的問題在于變量b是指外部用var聲明的變量b呢,還是立即執行的具名函數b呢?

如果b是立即執行的具名函數名稱,說實話我也不大確定它是否是可修改。

(ps:大多數的js書籍中都沒有明確指出立即執行函數表達式是否能重新賦值的問題)

但是我一定可以確定的是,如果b是指外部用var聲明的,那么在此代碼中它一定是可修改的。我們都知道用var聲明的全局變量它在任何地方肯定是可以修改的,因為該變量處于作用域的最頂端。

所以在這里我想大膽做個假設:變量b是指立即執行的具名函數名稱b~

做完這個假設,我想說:

那意味著全局變量b在立即執行的具名函數b里訪問不到嗎?

其實不是的,全局變量b在立即執行的具名函數b是可被訪問的,只不過因為具名函數b的內部作用域里也存在了一個用function聲明的變量b,所以在代碼執行的時候js引擎首先找到用function聲明的變量b。正如書籍中講到的作用域查詢是通過從里到外向上查詢。

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

當然在非嚴格模式下,大家可以試著動手在立即執行的具名函數內部函數打印一下window.b,也可論證全局變量b在立即執行的具名函數b里可被訪問!代碼如下:

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

到這里,理清楚了立即執行函數b的內部作用域機制,我的疑問又萌生了:

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

后來,我查閱了資料,明白了IIFE函數的內部機制~

我所理解的是:

當遇到具名的函數表達式的時,會創建一個輔助的特定對象,將函數表達式的名稱作為唯一的key,用來存儲函數表達式的名稱,然后添加到函數的作用域鏈中,該值只讀,并且不可以被刪除,所以不能對該值進行操作。

所以,在嚴格模式下,一個不可修改的常量被修改之后就會報TypeError: Assignment to constant variable。

分析非嚴格模式的輸出 在非嚴格模式下會靜默失敗,所以不報錯。針對如上的分析之后,會輸出立即執行的具名函數b本身。

code擴展

我將代碼改寫成:

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

那這段又會輸出什么呢?

無論在非嚴格模式還是在嚴格模式下,這段代碼都會輸出10,也就是全局變量b的值~

寫這段代碼的本意并不是為了猜測結果而想的,我想表達的是:為什么立即執行具名函數b在外部是不可訪問的?難道所有的表達式在外部都不可訪問嗎?

為了解決我的疑問,我通過如下函數foo1和foo2進行分析:

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

片段1

是讓一個匿名函數表達式賦值給變量foo1,然后該函數可以用foo1這個名稱進行訪問——foo1()。所以打印是一個函數。

片段2

是一個函數表達式,但結果是Uncaught ReferenceError: foo2 is not defined。說明在外部是不可訪問的。

可見,立即執行具名函數b是一個函數表達式,在外部是不可訪問的!(ps:意味著函數表達式既不可能通過名稱在函數聲明之前調用它,也不可能在聲明之后調用它)。

其實,大多數書籍里介紹以及我之前所理解的片段1這樣的代碼就是一個函數表達式。但現在我的理解并不是這樣的~

foo1是一個變量,匿名函數表達式賦值給變量foo1了,所以foo1它可被訪問!

通過自己寫了2個代碼片段,將我的疑惑迎刃而解了~

思考其他案例

在閑暇之余,我將最原始的代碼塊再做了改造,運用這些代碼來溫故并且思考了之前學習的理論基礎。

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

  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 

為什么會打印10呢,而不是函數b呢?

論據:函數聲明優先于變量聲明~

所以,相當于先利用function聲明了函數b,再利用var重寫了b。

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

為什么會打印函數b的執行結果12和1呢,而不是全局變量b呢?

論據:函數聲明優先于變量聲明~并且在這個過程中存在變量提升。

片段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函數,1 

為什么會打印10呢,而不是函數b呢?

論據:這個過程就是將變量b進行重新賦值。

所以,打印的是10,而不是函數。

片段4

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

論據:用var聲明變量可以可重復聲明,但是用let聲明變量不可重復聲明。

所以js引擎要執行完var b = 10語句之后,遇到了let b之前報錯了。

總結

在寫業務代碼的時候,要盡量去避免聲明變量命名沖突的情況,因為以上案例的的寫法是不合理的,很容易出現意想不到的結果。

為何不規范要求自己而避開不必要的麻煩呢?

當然,我覺得在學習乏味難啃的理論基礎知識時,我覺得應該創造自己的想象力,多去實踐多去思考為什么會有這樣的結果呢?

根據理論證實結果!

這樣才會使得讓自己更加理解理論基礎,并且更好的運用它們,而不僅僅是背/記。

原文:juejin.cn/user/2189882895108616

本文轉載自微信公眾號「前端人」,可以通過以下二維碼關注。轉載本文請聯系前端人公眾號。

 

責任編輯:武曉燕 來源: 前端人
相關推薦

2014-09-02 10:55:25

iOS開發視圖切換

2017-10-11 13:06:16

云計算云成本服務器

2017-08-15 10:53:34

網站設計UIUE

2020-04-20 09:01:50

程序員創業 互聯網

2010-10-09 09:18:59

Shell腳本

2019-05-27 22:59:39

面試SQL語句數據庫

2019-02-18 15:15:41

人工智能AI開發者

2014-07-08 09:21:10

死代碼創意歌曲

2022-06-21 12:27:12

JavaScript前端

2018-06-19 08:02:00

統計程序微信

2020-12-31 10:14:42

防注入代碼繞過

2021-11-24 08:51:32

Node.js監聽函數

2023-02-28 23:04:15

2021-02-04 07:55:28

代碼離職互聯網

2021-04-08 09:14:24

js前端函數

2021-07-01 10:01:16

JavaLinkedList集合

2021-08-14 10:01:43

Python條件語句Python基礎

2015-03-27 11:34:59

JavaJava編寫引發內存泄露

2020-12-29 09:05:48

基礎DjangoORM

2020-04-16 13:58:47

Java代碼框架
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产成人久久精品一区二区三区 | 久久er99热精品一区二区 | 午夜在线精品 | 日韩欧美大片在线观看 | 夜夜夜夜夜夜曰天天天 | 国产精品视频综合 | 欧美日韩久久精品 | av网址在线 | 午夜小视频免费观看 | 欧美精品三区 | 免费一区二区 | 国产一区二区三区四区三区四 | 免费午夜视频在线观看 | 日本精品视频 | h视频免费观看 | 日韩中文一区 | 国产专区在线 | 久久高清亚洲 | 国内精品视频在线 | h视频在线免费看 | 一区二区三区四区国产 | 成人免费视频网 | 91极品欧美视频 | 一本一道久久a久久精品综合蜜臀 | 国产精品久久久久久久免费大片 | 久久精品视频在线观看 | 91精品国产91久久久久久最新 | 久久蜜桃资源一区二区老牛 | 国产亚洲精品久久19p | 一级在线视频 | 亚洲精品久久久 | 欧美精品成人 | 亚洲国产看片 | 国产激情精品视频 | 亚洲精品无 | 伊人国产精品 | 91久久精品一区二区二区 | 午夜久久久久久久久久一区二区 | 日韩精品一区二区三区在线 | 午夜一区二区三区 | 色成人免费网站 |