摘要:詞法作用域定義在詞法階段的作用域由你在寫代碼時將變量和塊作用域?qū)懺谀膩頉Q定的,因此當(dāng)詞法分析器處理代碼時會保持作用域不變。欺騙詞法作用域在詞法分析器處理過后依然可以修改作用域。
你不知道的JS(上卷)筆記
你不知道的 JavaScript
JavaScript 既是一門充滿吸引力、簡單易用的語言,又是一門具有許多復(fù)雜微妙技術(shù)的語言,即使是經(jīng)驗豐富的 JavaScript 開發(fā)者,如果沒有認真學(xué)習(xí)的話也無法真正理解它們.
上卷包括倆節(jié):
作用域和閉包
this 和對象原型
作用域和閉包希望 Kyle 對 JavaScript 工作原理每一個細節(jié)的批判性思 考會滲透到你的思考過程和日常工作中。知其然,也要知其所以然。
詞法作用域作用域共有倆種主要的工作模型: 詞法作用域和動態(tài)作用域。
詞法階段詞法化:大部分標(biāo)準(zhǔn)語言編譯器的第一個工作階段叫作詞法化(也叫單詞化)。
詞法化的過程會對源代碼中的字符進行檢查,如果是有狀態(tài)的解析過程,還會賦 予單詞語義。
詞法作用域
定義在詞法階段的作用域
由你在寫代碼時將變量和塊作用域?qū)懺谀膩頉Q定的,因此當(dāng)詞法分析器處理代碼時會保持作用域不變。
欺騙詞法作用域: 在詞法分析器處理過后依然可以修改作用域。
事實上,讓詞法作用域根據(jù)詞法關(guān)系保持書寫時的自然關(guān)系不變是一個非常好的最佳實踐。
“作用域氣泡法” 劃分作用域
查找作用域氣泡的結(jié)構(gòu)和互相之間的位置關(guān)系給引擎提供了足夠的位置信息,引擎用這些信息來查找標(biāo)識符的位置。
作用域查找始終從運行時所處的最內(nèi)部作用域開始,逐級向外或者向上進行。
作用域查找會在找到第一個匹配的標(biāo)識符時停止,或者直至找到最后一個全局作用域處。
window.a的方式可以訪問那些被同名變量遮蔽了的全局變量,但非全局變量如果被遮蔽,就無法訪問到了
遮蔽效應(yīng): 在多層的嵌套作用域中可以定義同名的標(biāo)識符。
欺騙詞法倆種欺騙手段:eval和with;
社區(qū)認為使用這倆種機制并不是什么好主意,因為使用這倆種機制會導(dǎo)致性能下降
另外一個不推薦使用 eval(..) 和 with 的原因是會被嚴格模式所影響(限 制)。with 被完全禁止,而在保留核心功能的前提下,間接或非安全地使用 eval(..) 也被禁止了。
JavaScript 中的 eval(..) 函數(shù)可以接受一個字符串為參數(shù),并將其中的內(nèi)容視為好像在書 寫時就存在于程序中這個位置的代碼。換句話說,可以在你寫的代碼中用程序生成代碼并 運行,就好像代碼是寫在那個位置的一樣。
function foo(str, a) { eval( str ); // 欺騙! console.log( a, b ); } var b = 2; foo( "var b = 3;", 1 ); // 1, 3
eval通常被用來執(zhí)行動態(tài)創(chuàng)建的代碼
在這個例子中,為了展示的方便和簡潔,我們傳遞進去的“代碼”字符串是 固定不變的。而在實際情況中,可以非常容易地根據(jù)程序邏輯動態(tài)地將字符 拼接在一起之后再傳遞進去。eval(..) 通常被用來執(zhí)行動態(tài)創(chuàng)建的代碼,因 為像例子中這樣動態(tài)地執(zhí)行一段固定字符所組成的代碼,并沒有比直接將代 碼寫在那里更有好處。
在嚴格模式的程序中,eval(..) 在運行時有其自己的詞法作用域,意味著其 中的聲明無法修改所在的作用域。
類似:setTimeout的第一個參數(shù)為字符串時;new Function的最后一個字符串參數(shù);等都不提倡,不要使用。
withwith 通常被當(dāng)作重復(fù)引用同一個對象中的多個屬性的快捷方式,可以不需要重復(fù)引用對象 本身。
例如:
var obj = { a: 1, b: 2, c: 3 }; // 單調(diào)乏味的重復(fù) "obj" obj.a = 2; obj.b = 3; obj.c = 4; // 簡單的快捷方式 with (obj) { a = 3; b = 4; c = 5; } // 但實際上這不僅僅是為了方便地訪問對象屬性??紤]如下代碼: function foo(obj) { with (obj) { a = 2; } } var o1 = { a: 3 }; var o2 = { b: 3 }; foo( o1 ); console.log( o1.a ); // 2 foo( o2 ); console.log( o2.a ); // undefined console.log( a ); // 2——不好,a 被泄漏到全局作用域上了!
可以注意到一個奇怪的副作用,實際上 a = 2 賦值操作創(chuàng)建了一個全局的變量 a。這 是怎么回事?
with 可以將一個沒有或有多個屬性的對象處理為一個完全隔離的詞法作用域,因此這個對 象的屬性也會被處理為定義在這個作用域中的詞法標(biāo)識符。
盡管 with 塊可以將一個對象處理為詞法作用域,但是這個塊內(nèi)部正常的 var 聲明并不會被限制在這個塊的作用域中,而是被添加到 with 所處的函數(shù)作 用域中。
with 這種將對象及其屬性放進一個作用域并同時分配標(biāo)識符的行為很讓人費解。
性能JavaScript 引擎會在編譯階段進行數(shù)項的性能優(yōu)化。其中有些優(yōu)化依賴于能夠根據(jù)代碼的 詞法進行靜態(tài)分析,并預(yù)先確定所有變量和函數(shù)的定義位置,才能在執(zhí)行過程中快速找到 標(biāo)識符。
小結(jié)詞法作用域意味著作用域是由書寫代碼時函數(shù)聲明的位置來決定的。編譯的詞法分析階段 基本能夠知道全部標(biāo)識符在哪里以及是如何聲明的,從而能夠預(yù)測在執(zhí)行過程中如何對它 們進行查找。
JavaScript 中有兩個機制可以“欺騙”詞法作用域:eval(..) 和 with。前者可以對一段包 含一個或多個聲明的“代碼”字符串進行演算,并借此來修改已經(jīng)存在的詞法作用域(在 運行時)。后者本質(zhì)上是通過將一個對象的引用當(dāng)作作用域來處理,將對象的屬性當(dāng)作作 用域中的標(biāo)識符來處理,從而創(chuàng)建了一個新的詞法作用域(同樣是在運行時)。
這兩個機制的副作用是引擎無法在編譯時對作用域查找進行優(yōu)化,因為引擎只能謹慎地認 為這樣的優(yōu)化是無效的。使用這其中任何一個機制都將導(dǎo)致代碼運行變慢。不要使用它們。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/108971.html
摘要:如果提升改變了代碼執(zhí)行的順序,會造成非常嚴重的破壞。聲明本身會被提升,而包括函數(shù)表達式的賦值在內(nèi)的賦值操作并不會提升。要注意避免重復(fù)聲明,特別是當(dāng)普通的聲明和函數(shù)聲明混合在一起的時候,否則會引起很多危險的問題 你不知道的JS(上卷)筆記 你不知道的 JavaScript JavaScript 既是一門充滿吸引力、簡單易用的語言,又是一門具有許多復(fù)雜微妙技術(shù)的語言,即使是經(jīng)驗豐富的 Ja...
摘要:詞法作用域的查找規(guī)則是閉包的一部分。因此的確同閉包息息相關(guān),即使本身并不會真的使用閉包。而上面的創(chuàng)建一個閉包,本質(zhì)上這是將一個塊轉(zhuǎn)換成一個可以被關(guān)閉的作用域。結(jié)合塊級作用域與閉包模塊這個模式在中被稱為模塊。 你不知道的JS(上卷)筆記 你不知道的 JavaScript JavaScript 既是一門充滿吸引力、簡單易用的語言,又是一門具有許多復(fù)雜微妙技術(shù)的語言,即使是經(jīng)驗豐富的 Jav...
摘要:如果是聲明中的第一個詞,那么就是一個函數(shù)聲明,否則就是一個函數(shù)表達式。給函數(shù)表達式指定一個函數(shù)名可以有效的解決以上問題。始終給函數(shù)表達式命名是一個最佳實踐。也有開發(fā)者干脆關(guān)閉了靜態(tài)檢查工具對重復(fù)變量名的檢查。 你不知道的JS(上卷)筆記 你不知道的 JavaScript JavaScript 既是一門充滿吸引力、簡單易用的語言,又是一門具有許多復(fù)雜微妙技術(shù)的語言,即使是經(jīng)驗豐富的 Ja...
摘要:的抽象語法樹中可能會有一個叫作的頂級節(jié)點,接下來是一個叫作它的值是的子節(jié)點,以及一個叫作的子節(jié)點。值得注意的是,是非常重要的異常類型。嚴格模式下,未聲明的和倆者行為相同,都會是。 你不知道的JS(上卷)筆記 你不知道的 JavaScript JavaScript 既是一門充滿吸引力、簡單易用的語言,又是一門具有許多復(fù)雜微妙技術(shù)的語言,即使是經(jīng)驗豐富的 JavaScript 開發(fā)者,如果...
iKcamp官網(wǎng):http://www.ikcamp.com 訪問官網(wǎng)更快閱讀全部免費分享課程:《iKcamp出品|全網(wǎng)最新|微信小程序|基于最新版1.0開發(fā)者工具之初中級培訓(xùn)教程分享》。包含:文章、視頻、源代碼 showImg(https://segmentfault.com/img/remote/1460000011522427?w=1626&h=1242); 第二章:小程序中級實戰(zhàn)教程之預(yù)...
閱讀 810·2019-08-30 15:55
閱讀 1561·2019-08-30 15:52
閱讀 2719·2019-08-30 15:44
閱讀 2139·2019-08-30 11:14
閱讀 2650·2019-08-29 13:59
閱讀 1856·2019-08-29 13:45
閱讀 1039·2019-08-29 13:21
閱讀 3403·2019-08-26 13:31