正常來說,執行期上下文的作用域鍊是不會改變的
JavaScript中的詞法作用域並不是一成不變的
(詞法作用域/靜態作用域:作用域由書寫程式碼時函數宣告位置決定)
有幾種機制是可以欺騙詞法的
它們是with()、eval()還有try-catch語句的catch子句
其中with和eval我們不應該去使用(會產生很多問題)
欺騙詞法的意思就是欺騙詞法作用域
也就是說,它們在運行時改變了作用域鏈
下面我就來談談這些可以欺騙詞法的機制
eval
eval()函數接受一個字串作為參數,並且解析字串產生程式碼
var a = 123;eval('console.log(a)');// 123
於是控制台列印了123
執行了eval函數之後
js引擎並不知道這段程式碼時動態插入的,並且修改了作用域鏈
引擎還會像往常一樣查找作用域鏈
看下面的程式碼
var a = 1;function demo(){ eval('var a = 2;');//欺骗词法 console.log(a);// 2} demo();
當eval函數執行時,在demo函數執行環境的最頂端作用域添加了變數a
這個局部環境中的a「遮蔽」了全域環境的a
最終導致程式列印2
eval()函數不僅可以修改它目前所處的作用域,甚至可以修改全域作用域
無論怎樣,它都可以在運行期間修改詞法作用域
ES5的嚴格模式對這個函數加了一些限制,我把上面的程式碼加上局部嚴格模式
var a = 1;function demo(){ 'use strict'; eval('var a = 2;'); console.log(a);// 1} demo();
我們發現這回控制台印了1
這是因為在嚴格模式下, eval()運行時擁有自己獨立的詞法作用域(省的它給執行環境的作用域鏈搗亂)
這樣其中的聲明就無法修改它所在的作用域了
這種可以動態產生程式碼的還有兩個和它很像
計時器setTimeout()和setInterval()第一個參數可以是程式碼字串
還有函式建構器new Function()的最後一個參數同樣接受程式碼字串
和eval()一樣,不要使用這種用法,這會帶來嚴重的效能問題,這個問題一會兒再說
with
另一個不建議使用的欺騙詞法的語法就是這個with關鍵字
with通常用作重複引用某個物件的多個屬性的捷徑
好處是可以不需要重複的引用物件本身
例如我想重複使用console物件
console.log(1);console.info(2);console.warn(3);
使用with關鍵字
with(console){ log(1); info(2); warn(3); }
#看起來with好像沒什麼問題,但看下面
function demo(obj){ with(obj){ a = 5; } }var obj1 = {a:1};var obj2 = {b:2}; demo(obj1); console.log(obj1.a);// 5demo(obj2); console.log(obj2.a);// undefinedconsole.log(a);//5 -->变量a居然泄漏到了全局环境
我們發現使用with關鍵字修改了obj1的a
但是它不僅沒有在obj2上增加a,反而產生副作用洩漏到了全局
這是因為with可以把一個物件處理為一個完全隔離的詞法作用域(放到作用域鏈的最前面)
所以在它內部產生執行a = 5;
它會向下查找作用域鏈,但沒有找到,於是在全域創建了一個a變數(沒有var 的聲明)
注意:雖然with產生了一個詞法作用域,但是with內部的正常var聲明不會被限制在這個區塊作用域中
也就是說聲明在with外部的作用域
像這樣
function demo(){ var obj = {}; with(obj){ var b = 1; console.log(b); // 1 } console.log(b); // 1} demo(); console.log(b);// Uncaught ReferenceError: b is not defined
而且with關鍵字在ES5的嚴格模式乾脆就不讓用
如果你嘗試使用你會看到這樣的錯誤:
catch
除了eval與with之外,try-catch語句中的catch子句同樣可以修改執行環境的作用域鏈
當try程式碼區塊內發生錯誤,執行流立即跳到catch子句
隨後把異常物件推入一個可變物件並且放到作用域鏈最前面,這和with很像
一旦catch子句執行完畢,作用域鏈就會恢復原樣
但是和eval和with不同,try-catch還是相對有用,不用完全拋棄(雖然我沒用過)
性能
欺騙詞法會產生效能問題
js引擎在編譯階段會進行效能最佳化,許多最佳化依賴於能夠根據程式碼詞法進行靜態分析
預先確定了變數和函數的定義位置,才能快速找到標識符
但是eval或with無法判斷標識符位置(存在於程式碼執行過程中,無法靜態分析)
也就是說:在eval和with面前,js引擎所有的最佳化沒有任何意義(簡直酷炫)
既然沒意義,js引擎乾脆就不優化了
這樣就導致程式運行變慢了
對於with,它還有自己獨特的效能問題…
產生了作用域,就會導致它所在的函數的所有局部變數處於第二個作用鏈物件
存取代價更高了
對於try-catch語句,如果我們想要使用,可以這樣做
try{ ...}catch(e){ handleError(e); }
在catch語句中只執行了一段程式碼,委託給一個函數用於處理錯誤
這樣沒有局部變數的存取
作用域鏈的臨時改變就不會影響效能
總結
總結重點
#詞法作用域意味著作用域是書寫程式碼時函數宣告的位置來決定
編譯時詞法分析階段能知道所有標識符在哪裡及如何宣告eval可以對程式碼字串進行演算,藉此在執行時修改了詞法作用域
with透過將一個物件引用當作作用域來處理,藉此在運行時創建了詞法作用域
#eval在嚴格模式下會產生獨立詞法作用域,無法修改所在作用域
with在嚴格模式下禁止使用
eval與with(還有catch)可以欺騙詞法,在執行時修改作用域鏈
eval與with致使js引擎無法在編譯階段優化作用域查找(無法靜態分析),導致程式變慢
說了這麼多,就是要告訴大家不要使用with關鍵字與eval函數~( ̄0 ̄)/
以上就是JavaScript欺騙詞法的eval、with與catch及其效能問題的內容,更多相關內容請關注PHP中文網(www.php.cn )!

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

記事本++7.3.1
好用且免費的程式碼編輯器

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SublimeText3漢化版
中文版,非常好用

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器