最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript動態(tài)執(zhí)行JS代碼的四種方法

 更新時間:2025年06月17日 08:27:54   作者:程序員小寒  
這篇文章主要介紹了JavaScript動態(tài)執(zhí)行代碼的四種方法:eval、new Function、setTimeout及script標簽,并提及webpack中eval用于devtool配置,new Function優(yōu)化插件機制,強調安全性和性能差異,需要的朋友可以參考下

今天來聊一聊javascript如何動態(tài)執(zhí)行js代碼,我總結了以下四種方法。

第一種方式:eval

eval函數會將傳入的字符串作為js代碼執(zhí)行,并且返回最后一個表達式的值。

eval('console.log(1)') // 1

eval的特點:

  • 同步執(zhí)行;
  • 執(zhí)行環(huán)境為當前作用域。
let a = 1;
function test() {
  let a = 2;
  eval('console.log(a)'); // 2
}
test();

使用eval需要注意:

  • 安全風險:任何時候都不要把用戶的輸入放入eval中執(zhí)行,可能被注入惡意代碼(如 eval('alert("XSS")'))。
  • 性能差:eval 會中斷 JavaScript 引擎的優(yōu)化,導致執(zhí)行速度變慢。
  • 可讀性和維護性差:動態(tài)生成的代碼難以調試和維護。

第二種方式:new Function

可以通過構造函數Function動態(tài)創(chuàng)建一個函數,然后主動執(zhí)行它。

Function的函數簽名如下:

new Function([arg1, arg2, ...argN], functionBody)

其中,arg1, arg2, ...argN 是參數名,functionBody 是函數體。

let a = 1;
function test() {
  let a = 2;
  let fn = new Function('console.log(a)');
  fn(); // 1
}
test();

new Function的特點:

  • 同步執(zhí)行;
  • 執(zhí)行環(huán)境為全局作用域。

第三種方式:setTimeout

平常我們使用setTimeout第一個傳遞的是一個函數,第二個參數是延遲執(zhí)行的時間。

setTimeout(functionRef, delay);

但其實,setTimeout的第一個參數也可以是一個字符串,表示要執(zhí)行的代碼。

setTimeout('console.log(1)', 1000); // 1

來看看setTimeout執(zhí)行的作用域:

let a = 1;
function test() {
  let a = 2;
  setTimeout('console.log(a)', 1000); // 1
}
test();

所以setTimeout的特點如下:

  • 異步執(zhí)行;
  • 執(zhí)行環(huán)境為全局作用域。

第四種方式:script標簽

在瀏覽器環(huán)境中,我們可以動態(tài)創(chuàng)建script標簽來執(zhí)行代碼。

var a = 1;
let script = document.createElement('script');
script.textContent = 'console.log(1)';
document.body.appendChild(script); // 1

這個都不用多說了,肯定是全局作用域,所以script動態(tài)執(zhí)行的特點如下:

  • 同步執(zhí)行;
  • 執(zhí)行環(huán)境為全局作用域。

應用場景

動態(tài)執(zhí)行js這個功能在業(yè)務開發(fā)幾乎不用用到,但在一些打包工具中會用到,比如webpack。

1. devtool使用eval

webpack的配置文件webpack.config.js,有一項關于devtool的配置。

// webpack.config.js
module.exports = {
  devtool: 'eval-source-map',
}

當把devtool設置為eval-source-map時,webpack打包出來的代碼會使用eval進行包裹。

打包前的代碼:

// ./src/index.js
console.log(1)

打包后的產物長這樣,這里我使用的是webpack5。

// bundle.js
(() => {
  var __webpack_modules__ = ({
    "./src/index.js":
      (() => {
        eval("console.log(1)//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvaW5kZXguanMiLCJtYXBwaW5ncyI6IkFBQUEiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly93ZWJwYWNrLWRlbW8vLi9zcmMvaW5kZXguanM/YjYzNSJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zb2xlLmxvZygxKSJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/index.js\n");

      })

  });
  var __webpack_exports__ = {};
  __webpack_modules__["./src/index.js"]();
})();

這樣的好處是:

  • source-map映射內置在打包后的js文件中,不會生產單獨的source-map文件;
  • 由于是用eval直接包裹,所以構建速度快,適合開發(fā)環(huán)境調試使用。

順便提一下,開發(fā)環(huán)境一般會使用eval-cheap-module-source-map,相比于eval-source-map

  • cheap: 不生成列映射,只生成行映射,生成的映射文件體積更??;
  • module: 生成映射文件時,會保留模塊的路徑信息,方便調試。

生產環(huán)境如果需要調試的話,一般會使用全量的最完整的sourcemap,也就是devtool: 'source-map',這樣生成的映射文件雖然體積最大,但調試體驗最好。

2. tapable中使用 new Function

webpack的編譯過程中,tapable 實現了在編譯過程中的一種發(fā)布訂閱者模式的插件 Plugin 機制。在tapable的源碼中,就用到了new Function。

簡單舉個例子:

// Tapable 動態(tài)生成的調用函數(偽代碼)
const hook = new SyncHook(["arg1", "arg2"]);
hook.tap("plugin1", (arg1, arg2) => console.log(arg1, arg2));
hook.tap("plugin2", (arg1, arg2) => console.log(arg2, arg1));

這里用到了SyncHook做了一個監(jiān)聽,按傳統的發(fā)布訂閱的實現的話,內部會用callbacks.forEach(fn => fn(...args)))進行調用,每次觸發(fā)事件都需要動態(tài)遍歷回調數組,性能較低,所以tapablenew Function做了優(yōu)化。

// 動態(tài)生成的調用邏輯
const compiledFn = new Function("arg1", "arg2", `
 plugin1Fn(arg1, arg2);
 plugin2Fn(arg2, arg1);
`);
compiledFn("a", "b");

這里直接用new Function把邏輯進行動態(tài)組裝成一個函數,節(jié)省了上下文開銷,實現更加高效的事件觸發(fā)邏輯,尤其是在處理大量鉤子(Hooks)和插件時。

總結

主要介紹了四種動態(tài)執(zhí)行js的方法:

  • eval: 同步,當前作用域;
  • new Function: 同步,全局作用域;
  • script標簽: 同步,全局作用域;
  • setTimeout: 異步,全局作用域。

還簡單介紹了動態(tài)執(zhí)行的應用場景,比如webpackdevtool配置使用到了evaltapable中使用new Function。

以上就是JavaScript動態(tài)執(zhí)行JS代碼的四種方法的詳細內容,更多關于JavaScript動態(tài)執(zhí)行JS代碼的資料請關注腳本之家其它相關文章!

相關文章

  • Javascript 圓角div的實現代碼

    Javascript 圓角div的實現代碼

    為什么要做圓角的div: 圓角div平滑美觀,某些情況下有比較不錯的效果。比如說要做一個報message的消息框,那么動態(tài)的生成一個圓角div則很有意義。而對html樣式控制的css本身是不直接支持圓角div的。
    2009-10-10
  • 小程序實現瀑布流動態(tài)加載列表

    小程序實現瀑布流動態(tài)加載列表

    這篇文章主要為大家詳細介紹了小程序實現瀑布流動態(tài)加載列表,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • uniapp中微信小程序與H5相互跳轉以及傳參詳解(webview)

    uniapp中微信小程序與H5相互跳轉以及傳參詳解(webview)

    在單位做項目的時候碰到一個需求,需要從微信小程序跳轉到H5頁面,下面這篇文章主要給大家介紹了關于uniapp中微信小程序與H5相互跳轉以及傳參的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-08-08
  • 原生js實現的金山打字小游戲(實例代碼詳解)

    原生js實現的金山打字小游戲(實例代碼詳解)

    這篇文章主要介紹了原生js實現的金山打字小游戲,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • javascript笛卡爾積算法實現方法

    javascript笛卡爾積算法實現方法

    這篇文章主要介紹了javascript笛卡爾積算法實現方法,實例分析了笛卡爾積算法的javascript實現技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-04-04
  • JavaScript的Object.defineProperty詳解

    JavaScript的Object.defineProperty詳解

    本篇文章給大家詳細講述了JavaScript的Object.defineProperty的相關知識點內容,有興趣的朋友參考學習下。
    2018-07-07
  • 前端知識點之Javascript選擇輸入框confirm用法

    前端知識點之Javascript選擇輸入框confirm用法

    這篇文章主要介紹了JavaScript中的confirm方法的基本用法、功能特點、注意事項及常見用途,文中通過代碼介紹的非常詳細,對大家學習或者使用js具有一定的參考借鑒價值,需要的朋友可以參考下
    2025-02-02
  • OpenLayer學習之自定義測量控件

    OpenLayer學習之自定義測量控件

    這篇文章主要為大家詳細 介紹了OpenLayer學習之自定義測量控件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • 微信小程序五子棋游戲AI實現方法【附demo源碼下載】

    微信小程序五子棋游戲AI實現方法【附demo源碼下載】

    這篇文章主要介紹了微信小程序五子棋游戲AI實現方法,結合實例形式分析了五子棋游戲中人機對戰(zhàn)的AI原理及相關實現技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下
    2019-02-02
  • Firefox 無法獲取cssRules 的解決辦法

    Firefox 無法獲取cssRules 的解決辦法

    Firefox 無法獲取cssRules 的解決辦法...
    2006-10-10

最新評論

师宗县| 镇沅| 湘西| 小金县| 汉川市| 申扎县| 启东市| 清涧县| 利辛县| 汉沽区| 溧水县| 肃宁县| 莲花县| 遂溪县| 望谟县| 峨眉山市| 英山县| 天水市| 垣曲县| 收藏| 嘉义县| 卢龙县| 阜新| 台湾省| 会宁县| 淳安县| 南皮县| 泌阳县| 抚远县| 丰宁| 横山县| 泊头市| 泸定县| 水富县| 星座| 甘肃省| 长治市| 阿克苏市| 大新县| 北京市| 莒南县|