8

深入 JS new Function 语法

 2 years ago
source link: https://www.zhangxinxu.com/wordpress/2022/04/js-new-function/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

深入 JS new Function 语法

这篇文章发布于 2022年04月30日,星期六,23:41,归类于 JS API。 阅读 561 次, 今日 237 次 一条评论

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=10393 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

卡通动物封面图

语法如下:

let func = new Function ([arg1, arg2, ...argN], functionBody);

最后一个参数一定是函数体,其余参数都作为传给函数体的参数。

let sum = new Function('a', 'b', 'return a + b');

console.log(sum(1, 2)); // 结果是 3

平常进行 JS 或者 Node.js 开发的时候,我们是没有任何理由使用 new Function 构造函数的,因为没必要,直接使用 function 或者 () => {} 箭头函数写法就好了。

那是不是表示 new Function 语法是个鸡肋特性呢?

不!绝不是!

new Function 语法有个特别厉害的特性,使其成为 JavaScript 这门语言中无可替代的重要角色。。

什么特性呢?

那就是函数体的数据格式是字符串,这可是个不得了的东西啊!

二、无可替代的作用

举几个例子,展示下 new Function 的精妙作用。

1. 非合法 JSON 对象字符串合法化

例如,有下面一段字符串:

let str = `{ "id": 10393, name: 'zhangxinxu', 'date': '2022-04-30' }`;

其中的字符串不符合 JSON 格式(键值需要双引号),此时如果使用 JSON.parse() 进行解析是会报错的。

截图示意:

JSON 报错示意

那有什么办法将这段字符串对象转换成 JSON 可以解析的呢?

很多人会想到进行正则匹配再替换,或者使用 eval 这样糟粕的属性进行处理。

无需这么麻烦,new Function 出马,马到成功!

JS 代码如下所示:

console.log(JSON.stringify(new Function('return ' + str)()));
// 返回结果是:'{"id":10393,"name":"zhangxinxu","date":"2022-04-30"}'

运行结果截图:

JSON 字符串合法化

配合 return 语法,可以轻轻松松将任意的字符串转换成其他 JS 数据类型。

2. 模板字符串作为模板

这个应用在“ES6模板字符串在HTML模板渲染中的应用”这篇文章中有详细的介绍,我这里再简单介绍下。

例如现在的Vue,React等,都有自己的模板语法,例如 {} 这样子的语法等。

如果我们希望直接使用 ES6 自带的语法作为模板语言,则必须要借助 new Function 的能力了,例如有如下 HTML:

<template id="template">
  ${data.map(function (obj, index) {
    return `<p>文章:${obj.article}</p>
<p>作者:${obj.author}</p>
`;
  }).join('')}
</template>

我们可以扩展字符串,定义个名为 interpolate 的字符串方法,让 ES6 的语法字符串变成可执行的 ES6 代码:

String.prototype.interpolate = function (params) {
    const names = Object.keys(params);
    const vals = Object.values(params);

    return new Function(...names, `return \`${this}\`;`)(...vals);
};

此时,只需要有对应的数据,我们就可以基于 <template> 模板获得最终编译的 HTML 字符串,例如:

const html = template.innerHTML.interpolate({
  data: [{
    article: '文章标题1',
    author: '张鑫旭'
  }, {
    article: '文章标题2',
    author: 'CSS新世界'
  }]
});

console.log(html);

可以得到如下截图所示的结果:

模板处理结果示意

可以看到,无需任何第三方的模板渲染引擎,就可以使用复杂语法下的模板渲染效果,原生 JS 爱好者狂喜。

三、闭包与上下文

new Function 主体参数中的变量的上下文是全局的,而不是私有的,没有所谓的闭包。

举个例子,下面 new Function 代码中的 value 和主体函数中的 value 是没有关联的:

function getFunc() {
  let value = 'zhangxinxu';

  let func = new Function('console.log(value)');

  return func;
}

getFunc()(); // 报错: value 未定义
value 未定义

如果是常规的 function 函数语法,则不会有问题:

function getFunc() {
  let value = 'zhangxinxu';
  let func = function () {
    console.log(value)
  };

  return func;
}

getFunc()(); // 打印 'zhangxinxu'

常规用法的闭包

和 new Funciton 语法类似的还有 new RegExp,可以将字符串作为正则表达式内容,特别使用在动态匹配,或者增加代码混淆(有些混淆工具可以对字符串进行混淆)的场合。

例如,匹配动态的 value 开头的属性值,则可以使用下面的用法:

let reg = new RegExp('^' + value, 'g');

四、五一节快乐

今年五一节连休五天,今天第一天,赶在四月的尾巴写完这篇文章(现在23:11)。

接下来四天争取小说重写结束,然后开始《CSS选择器世界》第二版的撰写,因为疫情,合同还没寄过来。

说到疫情,还有其他糟心的事情。

上午出门做核酸出的急,忘记带钥匙,只能找人开锁。

结果疫情期间,为防止传播,开锁的人需要在公安备案才行,但是符合条件的人很少,于是,就滋生了个体垄断。

于是开锁价格那是惊为天人,先是锁撬不开(不知道真撬不开还是假的),然后换了个锁,报价1400,还到1200。

关键是换的锁烂的不得了,外面的金属有开锁人的手机号(打在金属上的),锁芯颜色完全不对,松动,还可以拔出几厘米,且内部无法钥匙反锁。

牛逼!估计是开锁的自己定制了个外面的锁壳,里面用了个以前撬锁弄下来的锁芯糊弄了下,收了我1200,估计成本顶多 200,奥利给!

就今天这一会儿,我们先是在外面等了1个小时(前面有1~2家),弄完我家匆忙去下一家,一上午至少赚3千,无需交税,这一两个月,月利润十万妥妥的。 ​​​

以后我儿子学习不好,我就让他学开锁!

1f48a.svg

(本篇完)1f44d.svg 是不是学到了很多?可以分享到微信
1f44a.svg 有话要说?点击这里

本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=10393


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK