你需要深入了解一下 JavaScript 的 new Function
1、語法
語法如下:
let func = new Function ([arg1, arg2, …argN], functionBody);
最后一個(gè)參數(shù)必須是函數(shù)體,其余參數(shù)作為傳遞給函數(shù)體的參數(shù)。
例如:
let sum = new Function('a', 'b', 'return a + b');
console.log(sum(1, 2)); // the result is 3
我們平時(shí)開發(fā) JavaScript 或者 Node.js 的時(shí)候,沒有理由使用 new Function 構(gòu)造函數(shù),因?yàn)椴恍枰苯邮褂煤瘮?shù)或者 () => {} 箭頭函數(shù)。
這是否意味著 new Function 語法是一個(gè)雞肋的功能?
千萬不要這樣想! 因?yàn)樗^對(duì)不是你想的那樣!
new Function 語法有一個(gè)特別強(qiáng)大的特性,使它在 JavaScript 中發(fā)揮著不可替代的作用。
有什么特點(diǎn)?也就是函數(shù)體的數(shù)據(jù)格式是字符串,真是不可思議!
不可替代的角色
這里有幾個(gè)例子來展示 new Function 語法的微妙之處。
1).無效的 JSON 對(duì)象字符串合法化
例如,有以下字符串:
let str = `{ "id": 103, name: 'yh', 'date': '2022–07–06' }`;
其中的字符串不符合JSON格式(鍵值需要雙引號(hào)),使用JSON.parse()解析會(huì)報(bào)錯(cuò)。
那么,有沒有什么辦法可以把這個(gè)字符串對(duì)象轉(zhuǎn)換成可以解析的JSON呢?
很多人會(huì)想到正則匹配然后替換,或者使用eval等渣屬性進(jìn)行處理。
沒必要這么麻煩, new Function 上線了,就完美了!
JS 代碼如下所示:
console.log(JSON.stringify(new Function('return ' + str)()));
// The return result is: '{"id":10393,"name":"yh","date":"2022–07–06"}'
使用返回語法,你可以輕松地將任意字符串轉(zhuǎn)換為其他 JavaScript數(shù)據(jù)類型。
2).模板字符串作為模板
比如Vue、React等現(xiàn)在都有自己的模板語法,比如{}語法。
如果我們想直接使用 ES6 自己的語法作為模板語言,就必須使用 new Function 的能力,比如下面的 HTML:
<template id="template">
${data.map(function (obj, index) {
return `<p>Article: ${obj.article}</p>
<p>Author: ${obj.author}</p>
`;
}).join('')}
</template>
我們可以擴(kuò)展字符串并定義一個(gè)名為 interpolate 的字符串方法來將 ES6 語法字符串轉(zhuǎn)換為可執(zhí)行的 ES6 代碼:
String.prototype.interpolate = function (params) {
const names = Object.keys(params);
const vals = Object.values(params);return new Function(…names,`return \`${this}\`;`)(…vals);
};
至此,只要有對(duì)應(yīng)的數(shù)據(jù),我們就可以根據(jù)<template>模板獲取最終編譯好的HTML字符串,例如:
const html = template.innerHTML.interpolate({
data: [{
article: 'Article title one',
author: 'y'
}, {
article: 'Article title two',
author: 'h'
}]
});
console.log(html);
可以看出,無需任何第三方模板渲染引擎,就能使用復(fù)雜語法下的模板渲染效果,原生JS愛好者欣喜若狂。
3).閉包和上下文
new Function 的 body 參數(shù)中變量的上下文是全局的,不是私有的,沒有所謂的閉包。
例如,下面新函數(shù)代碼中的值與主函數(shù)中的值無關(guān):
function getFunc() {
let value = 'yh';
let func = new Function('console.log(value)');
return func;
}
getFunc()(); // error: value is not defined
如果是常規(guī)函數(shù)語法,沒有問題:
function getFunc() {
let value = 'yh';
let func = function () {
console.log(value)
};
return func;
}
getFunc()(); // print 'yh'
4).其他
與 new Function 語法類似的是新的RegExp,它可以使用字符串作為正則表達(dá)式的內(nèi)容,特別適合動(dòng)態(tài)匹配,或者增加代碼混淆(一些混淆工具可以對(duì)字符串進(jìn)行混淆)。
例如,要匹配以動(dòng)態(tài)值開頭的屬性值,可以使用以下用法:
let reg = new RegExp('^' + value, 'g');
總結(jié)
以上就是我今天跟你分享的關(guān)于new Function語法的知識(shí),希望對(duì)你有所幫助,如果你覺得有用的話,請(qǐng)記得點(diǎn)贊我,關(guān)注我,并將其分享給你身邊的朋友,也許能夠幫助到他。
最后,感謝你的閱讀,期待你的關(guān)注,我們一起快樂學(xué)編程。