ES6中new Function()语法及应用实例分析


Posted in Javascript onFebruary 19, 2020

本文实例讲述了ES6中new Function()语法及应用。分享给大家供大家参考,具体如下:

学习《ECMAScript6入门》中的模板字符串的案例中看见了new Function()创建函数的语法:

let str = 'return ' + '`Hello ${name}!`';
let func = new Function('name', str);
func('Jack') // "Hello Jack!"

上面的代码传入name参数和字符串函数体,字符串函数体由模板字符串提供,非常简洁方便。

为理解new Function,于是找到了下面这篇文章:

下文翻译自:https://javascript.info/new-function

这里有一个很少被用到的新建函数的方法,但是有时候不得不使用它。

语法

新建函数的语法:

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

换句话说,函数的参数(或更确切地说,各参数的名称)首先出现,而函数体在最后。所有参数都写成字符串形式。

通过查看示例,可以更容易理解。这是一个有两个参数的函数:

let sum = new Function('a', 'b', 'return a + b');
alert( sum(1, 2) ); // 3

如果所要新建的函数没有参数,那么new Function()只有一个函数体参数:

let sayHi = new Function('alert("Hello")');
sayHi(); // Hello

这个方式与其他方式最主要的不同点在于,函数是由在运行时传入的字符串创建的。

之前的所有声明都要求程序员在脚本中编写功能代码。

但new Function允许将任何字符串转换为函数。例如,我们可以从服务器接收新函数然后执行它:

let str = ... receive the code from a server dynamically ...
let func = new Function(str);
func();

它在非常特殊的情况下使用,例如当我们从服务器接收代码时,或者使用模板动态编译函数。对此的需求通常出现在开发的进阶阶段。

闭包(Closure)

通常,函数将它所创建的位置记录在特殊属性[[Environment]]中。 它引用了创建地点的词法环境。

但是当使用new Function()创建函数时,其[[Environment]]不是引用当前的词法环境,而是引用全局环境。

function getFunc() {
 let value = "test";
 let func = new Function('alert(value)');
 return func;
}
getFunc()(); // error: value is not defined

与常规方法比较:

function getFunc() {
 let value = "test";
 let func = function() { alert(value); };
 return func;
}
getFunc()(); // "test", 来自getFunc的词法环境

这个特殊的new Function表面看起来很奇怪,但在实践中显得非常有用。

想象一下,我们必须从字符串创建一个函数。在编写脚本时不知道该函数的代码(这就是我们不使用常规函数的原因),但在执行过程中将会知道。我们可能会从服务器或其他来源收到它。

我们的新函数需要与主脚本进行交互。

也许我们希望它能够访问外部的局部变量?

问题是在JavaScript发布到生产之前,它是使用minifier压缩的——一个通过删除额外的注释,空格来缩小代码的特殊程序,而且 - 重要的是,会将局部变量重命名为较短的变量。

例如,如果一个函数中有let userName,那么minifier会替换它为let a(或者如果a被占用,则用另一个字母替换),这个过程会在任何地方进行。这通常是一件安全的事情,因为被替换的变量是局部的,函数外部没有任何东西可以访问它。并且在函数内部,minifier取代了它的每一个提及。Minifiers很聪明,他们会分析代码结构,所以他们不会破坏任何东西。他们不是只会愚蠢地发现和替换。

但是,如果new Function可以访问外部变量,那么它将无法找到userName,因为userName在代码缩小后才作为字符串传入。

所以,即使我们可以在new Function中访问外部词汇环境,我们也会遇到minifiers的问题。

而这时,new Function的“特色”可以让我们免于犯错。

它强制执行更好的代码。如果我们需要将某些东西传递给由new Function创建的函数,我们应该将它作为参数显式传递(可以避免直接读取外部变量时产生的问题)。

我们的“sum”函数实际上是这样正确使用的:

let sum = new Function('a', 'b', 'return a + b');
let a = 1, b = 2;
// 外部变量作为参数传入
alert( sum(a, b) ); // 3

总结

语法:

let func = new Function(arg1, arg2, ..., body);

历史原因,参数也可以以逗号分隔的列表的形式给出。

这三个意思相同:

new Function('a', 'b', 'return a + b'); // 基础语法
new Function('a,b', 'return a + b'); // 逗号分隔
new Function('a , b', 'return a + b'); // 逗号加空格分隔

使用new Function创建的函数,其[[Environment]]引用全局词法环境,而不是包含该函数的外部词法环境。因此,他们不能使用外层的变量。但这确实很好,因为它可以使我们免于错误。明确地传递参数在架构上是一种更好的方法,并且不会在使用minifiers时不会产生问题。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容可查看本站专题:《JavaScript操作DOM技巧总结》、《JavaScript页面元素操作技巧总结》、《JavaScript事件相关操作与技巧大全》、《JavaScript查找算法技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript错误与调试技巧总结》

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
jquery 指南/入门基础
Nov 30 Javascript
ie focus bug 解决方法
Sep 03 Javascript
JS连连看源码完美注释版(推荐)
Dec 09 Javascript
自己实现ajax封装示例分享
Apr 01 Javascript
javascript中日期函数new Date()的浏览器兼容性问题
Sep 05 Javascript
AngularJS  $modal弹出框实例代码
Aug 24 Javascript
原生ajax处理json格式数据的实例代码
Dec 25 Javascript
Angular2 自定义validators的实现方法
Jul 05 Javascript
小程序云开发部署攻略(图文教程)
Oct 30 Javascript
vue下拉菜单组件(含搜索)的实现代码
Nov 25 Javascript
vue 列表页跳转详情页获取id以及详情页通过id获取数据
Mar 27 Javascript
微信浏览器下拉黑边解决方案 wScroollFix
Jan 21 Javascript
es6中使用map简化复杂条件判断操作实例详解
Feb 19 #Javascript
JS继承定义与使用方法简单示例
Feb 19 #Javascript
深入浅析golang zap 日志库使用(含文件切割、分级别存储和全局使用等)
Feb 19 #Javascript
vue中实现回车键登录功能
Feb 19 #Javascript
Vue中实现回车键切换焦点的方法
Feb 19 #Javascript
整理 node-sass 安装失败的原因及解决办法(小结)
Feb 19 #Javascript
Vue常用的全选/反选的示例代码
Feb 19 #Javascript
You might like
德生PL550的电路分析
2021/03/02 无线电
php adodb介绍
2009/03/19 PHP
PHP 5.3.1 安装包 VC9 VC6不同版本的区别是什么
2010/07/04 PHP
PHP 提取图片img标记中的任意属性的简单实例
2013/12/10 PHP
浅析Yii2 GridView 日期格式化并实现日期可搜索教程
2016/04/22 PHP
php封装的smarty类完整实例
2016/10/19 PHP
Yii 框架使用数据库(databases)的方法示例
2020/05/19 PHP
AeroWindow 基于JQuery的弹出窗口插件
2011/06/27 Javascript
js不完美解决click和dblclick事件冲突问题
2012/07/16 Javascript
基于JQuery的多标签实现代码
2012/09/19 Javascript
jQuery学习笔记之 Ajax操作篇(三) - 过程处理
2014/06/23 Javascript
jQuery焦点图切换简易插件制作过程全纪录
2014/08/27 Javascript
js获取当前时间显示在页面上并每秒刷新
2014/12/24 Javascript
jQuery在页面加载时动态修改图片尺寸的方法
2015/03/20 Javascript
Bootstrap每天必学之附加导航(Affix)插件
2016/04/25 Javascript
完美实现js焦点轮播效果(二)(图片可滚动)
2017/03/07 Javascript
node.js环境搭建图文详解
2018/09/19 Javascript
浅谈layui使用模板引擎动态渲染元素要注意的问题
2019/09/14 Javascript
vue使用nprogress实现进度条
2019/12/09 Javascript
html+vue.js 实现漂亮分页功能可兼容IE
2020/11/07 Javascript
[02:49]2018DOTA2亚洲邀请赛主赛事决赛日战况回顾 Mineski鏖战5局夺得辉耀
2018/04/10 DOTA
Python实现获取邮箱内容并解析的方法示例
2018/06/16 Python
Python抓新型冠状病毒肺炎疫情数据并绘制全国疫情分布的代码实例
2020/02/05 Python
Windows下Pycharm远程连接虚拟机中Centos下的Python环境(图文教程详解)
2020/03/19 Python
Python动态强类型解释型语言原理解析
2020/03/25 Python
详解python datetime模块
2020/08/17 Python
python打包生成so文件的实现
2020/10/30 Python
css3使用animation属性实现炫酷效果(推荐)
2020/02/04 HTML / CSS
Ralph Lauren英国官方网站:Ralph Lauren UK
2018/04/03 全球购物
土木工程实习生自我鉴定
2013/09/19 职场文书
《长征》教学反思
2014/04/27 职场文书
自查自纠工作总结
2014/10/15 职场文书
解除劳动关系协议书2篇
2014/11/28 职场文书
2015初中生物教研组工作总结
2015/07/21 职场文书
GTX1650super好不好 gtx1650super显卡属于什么级别
2022/04/08 数码科技
Golang连接并操作MySQL
2022/04/14 MySQL