js執(zhí)行字符串代碼的具體實(shí)現(xiàn)
一、適用場(chǎng)景
在業(yè)務(wù)中我們很少去將一個(gè)字符串作為代碼執(zhí)行,因?yàn)槌鲇诎踩紤],盡量不要直接在客戶端執(zhí)行用戶輸入的代碼。但是在造輪子或者框架開(kāi)發(fā)中,我們需要在解析完開(kāi)發(fā)者編寫(xiě)的代碼后,來(lái)手動(dòng)執(zhí)行這些字符串代碼。
二、具體實(shí)現(xiàn)
1. eval
eval是一個(gè)我們都知道的函數(shù),這個(gè)函數(shù)會(huì)將傳入的字符串當(dāng)做 JavaScript 代碼進(jìn)行執(zhí)行。所以我們很多時(shí)候會(huì)用它來(lái)執(zhí)行字符串代碼。
例如:
const log = `console.log('11')` eval(log) const testCode = ` function test() { console.log('test') } test() ` eval(testCode)
注:需要注意的是,eval是在當(dāng)前上下文執(zhí)行的代碼,如果字符串中的變量與當(dāng)前上下文的變量命名沖突,就會(huì)導(dǎo)致報(bào)錯(cuò)。
例如:
const test = 'test' const testCode = ` function test() { console.log('test') } test() ` eval(testCode)
因?yàn)槲覀冏约憾x了test,而字符串中又有test函數(shù),所以就發(fā)生了沖突,出現(xiàn)報(bào)錯(cuò)。
我們很難去避免字符串中的變量和當(dāng)前上下文的變量重復(fù),所以我們可以在自調(diào)用函數(shù)中執(zhí)行eval來(lái)解決這個(gè)問(wèn)題。
const test = 'test' const a = 1 const testCode = ` function test() { console.log('test') console.log(a) } test() ` ;(function () { const a = 2 eval(testCode) })()
這樣就沒(méi)問(wèn)題了,注:這里的a打印的是2,也就是我們自調(diào)用函數(shù)作用域的a。
2. new Function()
語(yǔ)法:new Function(arg0, arg1, /* …, */ argN, functionBody)
Function() 構(gòu)造函數(shù)創(chuàng)建 Function 對(duì)象。直接調(diào)用構(gòu)造函數(shù)可以動(dòng)態(tài)創(chuàng)建函數(shù),但可能會(huì)面臨一些安全性和類(lèi)似于 eval() 的性能問(wèn)題(但相對(duì)較?。?。然而,與具有訪問(wèn)本地作用域的 eval 不同,F(xiàn)unction 構(gòu)造函數(shù)創(chuàng)建的函數(shù)僅在全局作用域中執(zhí)行。
例如:
const test = 'test' const a = 1 const testCode = ` function test() { console.log('test') console.log(a) } test() ` ;(function () { const a = 2 const func = new Function(testCode) func() })()
注:當(dāng)前的a打印的是1,也就是Function 構(gòu)造函數(shù)創(chuàng)建的函數(shù)僅在全局作用域中執(zhí)行。里面的未定義的變量會(huì)直接使用全局的變量。
如何解決這個(gè)問(wèn)題?
創(chuàng)建function的時(shí)候支持傳遞參數(shù),我們可以通過(guò)參數(shù)傳遞來(lái)解決。
const test = 'test' const a = 1 const testCode = ` function test() { console.log('test') console.log(a) } test() ` ;(function () { const a = 2 const func = new Function('a', testCode) func(a) })()
我們將a傳遞作為參數(shù)傳遞到了func中,實(shí)際上func現(xiàn)在就相當(dāng)于:
function func(a) { function test() { console.log('test') console.log(a) } test() }
這種方式就不用但是上下文命名沖突的問(wèn)題,因?yàn)榇a是在函數(shù)中執(zhí)行的,因此我們不需要在自調(diào)用函數(shù)中運(yùn)行 new Function()。
并且通過(guò)這種方式我們還能接受到字符串代碼中的返回。
const test = 'test' const sum = `return a + b` const func = new Function('a', 'b', sum) console.log(func(2, 3))
三、兩者差異
- eval是在當(dāng)前上下文執(zhí)行代碼,會(huì)出現(xiàn)變量命名沖突,而new Function()是在函數(shù)內(nèi)部執(zhí)行,不會(huì)出現(xiàn)沖突
- eval的作用域是當(dāng)前執(zhí)行位置的作用域,而new Function()的作用域是全局
- eval不能傳遞參數(shù),也不能接受返回值,new Function()可以傳遞參數(shù)并接收返回值
所以如果是大量的執(zhí)行字符串代碼,建議使用new Function()的方式,它更強(qiáng)大(比如Vue框架就使用new Function()的方式)。如果你只是偶爾使用,并且對(duì)參數(shù)、命名也沒(méi)要求,那就直接使用eval,更加簡(jiǎn)單方便。
附:結(jié)合eval和new Function()一起實(shí)現(xiàn)
try { const val = new Function(“要執(zhí)行的字符串”); let eleResult = val(); // 這里必須調(diào)用val(),不然不會(huì)執(zhí)行 if (!eleResult) { eleResult = eval(“要執(zhí)行的字符串”); } } catch (err) { console.info(‘執(zhí)行字符串js出錯(cuò)'); }
到此這篇關(guān)于js執(zhí)行字符串代碼具體實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)js執(zhí)行字符串代碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript對(duì)象Clone實(shí)例分析
這篇文章主要介紹了Javascript對(duì)象Clone用法,實(shí)例分析了javascript對(duì)象克隆的相關(guān)技巧,需要的朋友可以參考下2015-06-06javascript變量作用域使用中常見(jiàn)錯(cuò)誤總結(jié)
剛看了一篇文章對(duì)js作用域的理解又會(huì)上升到一個(gè)新的臺(tái)階,javascript里變量作用域是個(gè)經(jīng)常讓人頭痛抓狂的問(wèn)題,接下來(lái)對(duì)經(jīng)常遇到又容易出錯(cuò)的情況進(jìn)行了簡(jiǎn)單總結(jié),感興趣的各位可以參考下哈2013-03-03使用JavaScript實(shí)現(xiàn)小球按照貝塞爾曲線運(yùn)動(dòng)
要在 JavaScript 中實(shí)現(xiàn)一個(gè)按照貝塞爾曲線運(yùn)動(dòng)的小球,關(guān)鍵是要掌握貝塞爾公式的基本原理和實(shí)現(xiàn)方式,以及使用 JavaScript 處理動(dòng)畫(huà)和物理運(yùn)算,感興趣的小伙伴跟著小編一起來(lái)看看吧2024-10-10js仿蘋(píng)果iwatch外觀的計(jì)時(shí)器代碼分享
這篇文章主要介紹了JS+CSS3實(shí)現(xiàn)的類(lèi)似于蘋(píng)果iwatch計(jì)時(shí)器特效,很實(shí)用的代碼,推薦給大家,有需要的小伙伴可以參考下。2015-08-08JS實(shí)現(xiàn)n秒后自動(dòng)跳轉(zhuǎn)的兩種方法
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)n秒后自動(dòng)跳轉(zhuǎn)的兩種方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07JavaScript實(shí)現(xiàn)shuffle數(shù)組洗牌操作示例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)shuffle數(shù)組洗牌操作,結(jié)合實(shí)例形式分析了javascript數(shù)組的定義、構(gòu)造、排序等相關(guān)操作技巧,需要的朋友可以參考下2019-01-01前端算法題解leetcode114二叉樹(shù)展開(kāi)為鏈表
這篇文章主要為大家介紹了前端算法題解leetcode114二叉樹(shù)展開(kāi)為鏈表,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09layui動(dòng)態(tài)設(shè)置單選按鈕選中效果實(shí)例
最近在使用layui前端框架,在使用單選按鈕、下拉菜單select、checkbox等控件的時(shí)候,往往遇到一些初始化的東西,下面這篇文章主要給大家介紹了關(guān)于layui動(dòng)態(tài)設(shè)置單選按鈕選中效果的相關(guān)資料,需要的朋友可以參考下2023-06-06