你不知道的js一

js的執(zhí)行過程
js代碼不是構(gòu)建之前進(jìn)行編譯的,而是在代碼執(zhí)行前很短的一段時間內(nèi),引擎沒有那么多的時間來進(jìn)行優(yōu)化

作用域

程序具有的基本功能之一,是能夠儲存變量,并在程序執(zhí)行時能夠找到變量的值,用來計算,涉及到變量的存儲和取值,有一套規(guī)則,就是作用域
在程序編譯的過程中,分三步

  • 首先是分詞,詞法分析,比如var a=1這個語句,會被拆為var a = 2,就是將所寫的代碼拆成代碼塊
  • 第二部,生成抽象語法樹,將第一步生成的代碼塊生成一個執(zhí)行的語法樹
  • 第三部,將抽象語法樹生成可執(zhí)行的代碼,即將var a=2生成機(jī)器可執(zhí)行的01代碼
var a=2的執(zhí)行過程

編譯器先進(jìn)行此法分析,生成語法解析樹,接下來會生成生成引擎執(zhí)行所需要的代碼

  • 假設(shè)生成的代碼邏輯:為一個變量a生成一個內(nèi)存空間,并把2賦給它
  • 實(shí)際上:編譯器遇到var a這個代碼,首先會詢問作用域是否已經(jīng)有a這個變量,如果有,編譯器會忽略這個變量聲明繼續(xù)編譯,如果沒有,則作用域會在當(dāng)前作用域的集合中聲明一個變量,并命名為a
    接下來編譯器為引擎生成a=2這個操作的可執(zhí)行代碼,引擎執(zhí)行過程中,會詢問當(dāng)前作用域是否存在a這個變量,如果存在,則將2賦給這個變量,如果不存在,引擎會繼續(xù)向上層作用域詢問是否存在,如果到了頂層沒找到,引擎結(jié)束查找,并拋出一個錯誤
    引擎拋出的錯誤類型
  • referceerror:引擎執(zhí)行RHS查找時,如果這個變量未聲明,會拋出referceerror錯誤,RHS查找一般用于取值操作,即賦值操作=右側(cè)的變量,在非嚴(yán)格模式下,進(jìn)行LHS查找,即賦值操作,引擎如果在全局作用域中沒有找到變量,則全局作用域會創(chuàng)建一個變量,并返回給引擎,并不會拋出錯誤
  • typeerror :試圖對一個變量進(jìn)行不合法的操作,比如調(diào)動string的push方法等

為什么會有變量提升
變量的聲明是編譯器在編譯階段就命令作用域進(jìn)行了聲明,在生成可執(zhí)行代碼之前

eval with

with標(biāo)識新創(chuàng)建了一個傳入的對象的作用域,當(dāng)其屬性存在時,賦值操作被綁定到with聲明的對象上,當(dāng)找不到對應(yīng)的屬性時,對變量的賦值操作執(zhí)行普通的賦值操作,即變量的作用域變成with所在的作用域,同時,with代碼塊內(nèi)的var聲明的變量作用域依然為with所在的作用域,

不推薦使用eval和with

函數(shù)作用域,隱藏變量和規(guī)避沖突
  • 函數(shù)表達(dá)式和函數(shù)聲明區(qū)別:函數(shù)名稱標(biāo)識符綁定的作用域不同,函數(shù)聲明標(biāo)識符可被外部作用域訪問,函數(shù)表達(dá)式僅可被用于函數(shù)內(nèi)部
  • 具名函數(shù)和匿名函數(shù)
  • 兩種立即執(zhí)行函數(shù)表達(dá)式的不同寫法
  • try catch let const 垃圾收集
變量提升
  • js代碼的執(zhí)行首先編譯器在編譯階段處理了所有的變量的聲明,然后才生成了可執(zhí)行代碼
  • 函數(shù)表達(dá)式,具名函數(shù)表達(dá)式在賦值之前,函數(shù)名并不會被提升,賦值變量會進(jìn)行提升
  • 函數(shù)聲明先于變量聲明
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容