給急躁的程式設計師的 JavaScript(ES2022 版本)
請支持這本書:購買捐款
(廣告,請不要封鎖。)

26 動態評估程式碼:eval()new Function()(進階)



在本章中,我們將探討兩種動態評估程式碼的方法:eval()new Function()

26.1 eval()

給定包含 JavaScript 程式碼的字串 streval(str) 會評估該程式碼並傳回結果

> eval('2 ** 4')
16

有兩種呼叫 eval() 的方法

「不透過函式呼叫」表示「任何看起來與 eval(···) 不同的東西」

以下程式碼說明了差異

globalThis.myVariable = 'global';
function func() {
  const myVariable = 'local';
  
  // Direct eval
  assert.equal(eval('myVariable'), 'local');
  
  // Indirect eval
  assert.equal(eval.call(undefined, 'myVariable'), 'global');
}

在全域內容評估程式碼比較安全,因為程式碼存取的內部較少。

26.2 new Function()

new Function() 會建立一個函式物件,並以以下方式呼叫

const func = new Function('«param_1»', ···, '«param_n»', '«func_body»');

前一個陳述式等同於下一個陳述式。請注意,«param_1» 等不再在字串文字內。

const func = function («param_1», ···, «param_n») {
  «func_body»
};

在以下範例中,我們建立了同一個函式兩次,第一次透過 new Function(),然後透過函式表達式

const times1 = new Function('a', 'b', 'return a * b');
const times2 = function (a, b) { return a * b };

  new Function() 會建立非嚴格模式函式

預設情況下,透過 new Function() 建立的函式是寬鬆的。如果我們希望函式主體處於嚴格模式,則必須手動開啟

26.3 建議

盡量避免動態評估程式碼

JavaScript 經常是動態的,因此您不需要 eval() 或類似的函式。在以下範例中,我們使用 eval() (A 行) 所執行的動作,也可以在沒有它的情況下順利執行 (B 行)。

const obj = {a: 1, b: 2};
const propKey = 'b';

assert.equal(eval('obj.' + propKey), 2); // (A)
assert.equal(obj[propKey], 2); // (B)

如果您必須動態評估程式碼