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

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

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

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

第一種方式:eval

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

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

eval的特點(diǎn):

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

使用eval需要注意:

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

第二種方式:new Function

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

Function的函數(shù)簽名如下:

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

其中,arg1, arg2, ...argN 是參數(shù)名,functionBody 是函數(shù)體。

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

new Function的特點(diǎn):

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

第三種方式:setTimeout

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

setTimeout(functionRef, delay);

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

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

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

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

所以setTimeout的特點(diǎn)如下:

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

第四種方式:script標(biāo)簽

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

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

這個(gè)都不用多說(shuō)了,肯定是全局作用域,所以script動(dòng)態(tài)執(zhí)行的特點(diǎn)如下:

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

應(yīng)用場(chǎng)景

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

1. devtool使用eval

webpack的配置文件webpack.config.js,有一項(xiàng)關(guān)于devtool的配置。

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

當(dāng)把devtool設(shè)置為eval-source-map時(shí),webpack打包出來(lái)的代碼會(huì)使用eval進(jìn)行包裹。

打包前的代碼:

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

打包后的產(chǎn)物長(zhǎng)這樣,這里我使用的是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映射內(nèi)置在打包后的js文件中,不會(huì)生產(chǎn)單獨(dú)的source-map文件;
  • 由于是用eval直接包裹,所以構(gòu)建速度快,適合開發(fā)環(huán)境調(diào)試使用。

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

  • cheap: 不生成列映射,只生成行映射,生成的映射文件體積更?。?/li>
  • module: 生成映射文件時(shí),會(huì)保留模塊的路徑信息,方便調(diào)試。

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

2. tapable中使用 new Function

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

簡(jiǎn)單舉個(gè)例子:

// Tapable 動(dòng)態(tài)生成的調(diào)用函數(shù)(偽代碼)
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做了一個(gè)監(jiān)聽,按傳統(tǒng)的發(fā)布訂閱的實(shí)現(xiàn)的話,內(nèi)部會(huì)用callbacks.forEach(fn => fn(...args)))進(jìn)行調(diào)用,每次觸發(fā)事件都需要?jiǎng)討B(tài)遍歷回調(diào)數(shù)組,性能較低,所以tapablenew Function做了優(yōu)化。

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

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

總結(jié)

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

  • eval: 同步,當(dāng)前作用域;
  • new Function: 同步,全局作用域;
  • script標(biāo)簽: 同步,全局作用域;
  • setTimeout: 異步,全局作用域。

還簡(jiǎn)單介紹了動(dòng)態(tài)執(zhí)行的應(yīng)用場(chǎng)景,比如webpackdevtool配置使用到了eval,tapable中使用new Function

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

相關(guān)文章

  • Javascript 圓角div的實(shí)現(xiàn)代碼

    Javascript 圓角div的實(shí)現(xiàn)代碼

    為什么要做圓角的div: 圓角div平滑美觀,某些情況下有比較不錯(cuò)的效果。比如說(shuō)要做一個(gè)報(bào)message的消息框,那么動(dòng)態(tài)的生成一個(gè)圓角div則很有意義。而對(duì)html樣式控制的css本身是不直接支持圓角div的。
    2009-10-10
  • 小程序?qū)崿F(xiàn)瀑布流動(dòng)態(tài)加載列表

    小程序?qū)崿F(xiàn)瀑布流動(dòng)態(tài)加載列表

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

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

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

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

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

    javascript笛卡爾積算法實(shí)現(xiàn)方法

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

    JavaScript的Object.defineProperty詳解

    本篇文章給大家詳細(xì)講述了JavaScript的Object.defineProperty的相關(guān)知識(shí)點(diǎn)內(nèi)容,有興趣的朋友參考學(xué)習(xí)下。
    2018-07-07
  • 前端知識(shí)點(diǎn)之Javascript選擇輸入框confirm用法

    前端知識(shí)點(diǎn)之Javascript選擇輸入框confirm用法

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

    OpenLayer學(xué)習(xí)之自定義測(cè)量控件

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

    微信小程序五子棋游戲AI實(shí)現(xiàn)方法【附demo源碼下載】

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

    Firefox 無(wú)法獲取cssRules 的解決辦法

    Firefox 無(wú)法獲取cssRules 的解決辦法...
    2006-10-10

最新評(píng)論

泊头市| 石家庄市| 芦山县| 铜山县| 松桃| 沂水县| 徐闻县| 开化县| 崇左市| 获嘉县| 安塞县| 英超| 密山市| 高安市| 文登市| 垫江县| 红原县| 昭通市| 尼玛县| 巴青县| 隆昌县| 博爱县| 甘孜| 宜阳县| 晋江市| 崇文区| 嘉黎县| 博白县| 航空| 高邮市| 鄂托克前旗| 重庆市| 开平市| 磐石市| 富宁县| 利川市| 宁晋县| 新津县| 宜兰县| 瑞金市| 抚宁县|