JavaScript 考題之不使用 eval 的狀況下來做計算

前言

最近看到有人分享一個滿有趣的題目,所以就順手簡單稍微寫成文章記錄一下,或許哪一天自己會回來看這一篇。

題目

首先題目是這樣子

1
const a = '1 + 2 + 3';

請將上述的 a 變數的值,做計算後,得到 6 的結果。

解題思維

接下來,這邊我稍微記錄一下自己的解題思維…

eval

首先這邊先提一個最簡單的解題方式,也就是使用 eval 來做計算

1
2
3
const a = '1 + 2 + 3';

eval(a); // 6

但是通常來講 eval 這個函式並不建議使用,為什麼呢?來看一下 MDN 關於 eval描述與說明

The eval() function evaluates JavaScript code represented as a string and returns its completion value. The source is parsed as a script.

上面這個描述翻譯成中文的意思是指…

eval 函式會將傳入的字串當成 JavaScript 的程式碼來執行,並回傳結果。」

看起來很方便對吧?如果你的專案有使用 ESLint 來去管理風格的話,基本上你會發現 ESLint 會要求你不要去使用 eval 這個函式,因為這個函式會有一些安全性的問題,例如說你可以透過 eval 來執行一些惡意的程式碼,例如說

1
2
3
const a = 'alert("是 Ray 不是 Array")';

eval(a); // 會跳出一個 alert 視窗,並且顯示「是 Ray 不是 Array」

Alert

因此滿多考題上面都會禁止你使用 eval 這個函式,更不用說 MDN 本身也已經有標註這個函式是不建議使用的

Warning: Executing JavaScript from a string is an enormous security risk. It is far too easy for a bad actor to run arbitrary code when you use eval(). See Never use eval()!, below.

new Function or Function

這時候可能就會想說,那可以用 new FunctionFunction 嗎?基本上 new FunctionFunction 也可以做到相同效果,底下以 new Function 為例

1
2
3
4
5
6
7
const a = '1 + 2 + 3';

const calc = (val) => {
return new Function(`return ${val}`)();
}

calc(a); // 6

但其實這個方式與 eval 一樣,也是不建議使用的,因為這個方式也會有一些安全性的問題

1
2
3
4
5
6
7
const a = 'alert("是 Ray 不是 Array")';

const calc = (val) => {
return new Function(`return ${val}`)();
}

calc(a); // 會跳出一個 alert 視窗,並且顯示「是 Ray 不是 Array」

Alert

所以 new FunctionFunction 也是不建議使用的,那這樣的話,我們就只能想其他的方式來解決這個問題了。

陣列操作方法

這個就比較特別一點了,將會使用 map 這個陣列操作函式來解決,先讓我們直接來看一下程式碼

1
2
3
4
const a = '1 + 2 + 3';
const b = a.split(' + '); // [ "1", "2", "3" ],將字串依照內容切割成陣列
const c = b.map(Number); // [ 1, 2, 3 ],將裡面的陣列轉換成數字
const total = c.reduce((acc, cur) => acc + cur); // 6,使用 reduce 來做相加

雖然這目前是可以符合我們想要的答案,但卻也會有一些缺點,例如說如果我們的字串是這樣子的

1
const a = '2 + (2 * 2)';

那麼使用 split 來切割的話,就會變成這樣子

1
const b = a.split(' + '); // [ "2", "(2 * 2)" ]

這樣子就會發生錯誤,因此這個做法比較適合用在簡單的計算上,如果是複雜的計算的話,就不適合使用這個做法了。

參考文獻

Liker 讚賞

這篇文章如果對你有幫助,你可以花 30 秒登入 LikeCoin 並點擊下方拍手按鈕(最多五下)免費支持與牡蠣鼓勵我。
或者你可以也可以請我「喝一杯咖啡(Donate)」。

Buy Me A Coffee Buy Me A Coffee

Google AD

撰寫一篇文章其實真的很花時間,如果你願意「關閉 Adblock (廣告阻擋器)」來支持我的話,我會非常感謝你 ヽ(・∀・)ノ