[JS] 動態執行JS與修改詞法作用域

来源:https://www.cnblogs.com/feixianxing/p/18252203/dynamically-execute-javascript-and-scope
-Advertisement-
Play Games

JS中有一些操作可以動態地執行JS代碼,並修改或新建詞法作用域,這種操作雖然帶來了更多的靈活性,但是會嚴重地影響到性能。 ...


相關可行的操作

  1. eval: 同步執行,當前作用域;
  2. setTimeout: 非同步執行,全局作用域;

第1個參數可以傳入函數對象,也可以傳入字元串,即要執行的代碼。

  1. script: 同步執行,全局作用域;

創建script標簽,並設置innerHTML為要執行的代碼。

  1. Function: 同步執行,全局作用域。

Function構造函數可以傳入字元串,生成一個函數對象。


對詞法作用域的影響

eval

eval可以通過動態地執行JS代碼從而修改(欺騙)當前的詞法作用域,觀察如下代碼:

function foo(str, a){
    eval(str);
    console.log(a, b);
}
var b = 2;
foo("var b=3;", 1); // 1, 3

在函數中,執行eval(..)var b=3;帶入該詞法作用域,導致console.log(..)中對b的右值引用找到的是3,而不會查詢到外部的b=2

在預設情況下,eval會對所處的詞法作用域進行修改。
嚴格模式下,eval在運行時有其自己的詞法作用域,即其動態執行的JS聲明語句不會影響到eval語句所處的詞法作用域。

function foo(str){
    "use strict";
    eval(str);
    console.log(a); // ReferenceError: a is not defined
}
foo("var a = 2;");

with

除了eval另外可以修改詞法作用域的語法是with關鍵字。

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被泄露到全局作用域了)

with接受一個對象,並將這個對象處理為一個完全隔離的詞法作用域,這個對象的屬性會被處理為定義在這個作用域內的詞法標識符。
所以當o1傳遞給with時,with聲明的作用域是o1,包含了同o1.a對應的標識符a,這個左值引用可以找到目標,併成功完成賦值操作。
o2傳遞給with時,with聲明的詞法作用域會包含同o2.b對應的標識符b,但是沒有標識符a,此時賦值操作會進行LHS標識符查詢,向外層作用域查找。
由於在o2的作用域、foo的函數作用域、全局作用域都沒有找到標識符a,因此當a = 2執行時,會在全局作用域自動創建一個全局變數(如果是嚴格模式則不會)。

性能問題

JS引擎會在編譯階段進行性能優化,其中部分優化依賴於根據代碼的詞法進行靜態分析,並預先確定所有變數和函數的定義位置,才能在執行過程中快速找到標識符。
evalwith這種可能動態更改詞法作用域的操作會導致JS引擎無法在詞法分析階段明確標識符的位置,因此所有優化可能都是無意義的,甚至JS引擎可能在讀取代碼中使用了evalwith,就放棄優化了。
因此,在開發中應該避免使用evalwith

引用

[1] Scope and Closures, Kyle Simpson著(O'Reilly, 2014) 978-1-491-33558-8。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 近日,全國智能計算標準化工作組算力互聯互通研究組啟動會在北京正式召開,來自中國工程院、工業和信息化部、中國信息通信研究院、全國智能計算標準化工作組的領導及智算行業知名企業代表和業內專家共襄盛舉,圍繞推進算力互聯互通展開交流碰撞,凝智聚力,共話行業生態,共謀算力發展。會上成立算力互聯互通國家標準研究組... ...
  • 1.開啟hive 1.首先在master的/usr/local/soft/下啟動hadoop: master : start-all.sh start-all.sh 2.在另一個master(2)上監控hive日誌: master(2): tail -F /tmp/root/hive.log tai ...
  • 轉載自東華果汁哥 Apache DophinScheduler 運行一段時間後,實例調度日誌越來越多,需要定期清理。 SQL 錯誤 [1701] [42000]: Cannot truncate a table referenced in a foreign key constraint (`dol ...
  • 本文提供了利用數據觸發Feishu Webhook的具體操作指南,包括Webhook的設置以及編寫觸發代碼的方法,為讀者提供了實踐參考,希望能幫助解決你目前遇到的問題。 描述 用於使用數據觸發 Feishu Webhook。 例如,如果來自上游的數據是 [age: 12, name: tyrantl ...
  • 目錄一、目的二、環境三、相關概念3.1 屏幕尺寸(screen size)3.2 屏幕解析度(Resolution)3.3 像素(pixel)3.4 ppi3.5 dpi3.6 dp/dip3.7 sp四、Q&A4.1 為啥dpi = 160?4.2 為啥Android要引入dp概念?五、代碼倉庫地 ...
  • 目錄效果圖思路具體實現步驟一:ItemView頂部偏移步驟二:繪製圓和線條註意:下標的獲取流程類的繪製總結 效果圖 可控制是否繪製在中間 控制繪製的線條是否為虛線 控制第一條數據圓頂部線條和最後一條數據圓底部線條是否繪製 除了gif圖片展示的屬性,還可以控制圓的大小顏色、圓是否有上和左偏移、線條顏色 ...
  • ‍ 寫在開頭 點贊 + 收藏 學會 在項目中我們可能會遇到當滑鼠在某個區域內,我們希望滾動滑鼠裡面的內容可以橫向滾動; 比如我們一些常見的後臺狀態欄: 那這種該怎麼寫?請看慄子 代碼如下: <template> <div> <div class="top"> <div class ...
  • 摘要:本文闡述了Nuxt.js作為基於Vue.js的伺服器端渲染框架,其在提升Web開發效率、確保代碼質量和優化應用性能方面的核心價值。通過詳盡的安裝步驟、配置說明、常見問題解決策略及進階部署方法,為開發者搭建和部署Nuxt.js項目提供了全方位指導。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...