深入理解new Function
基础语法
let func = new Function([arg1,arg2,arg3,...argN],functionBody)
函数是通过使用参数 arg1…argN 和给定的 functionBody 创建。
调用 Function 时可以使用或不使用 new,两者都会创建一个新的 Function 实例
举例1: 带有两个参数的函数
let sum = new Function('a', 'b', 'return a + b');
console.log(sum(1, 2)); // 3let sum1 = new Function('a', ' b', 'return a + b');
console.log(sum1(1, 2)); // 3let sum2 = new Function('a,b', 'return a + b');
console.log(sum2(1, 2)); // 3let sum3 = new Function('a , b', 'return a + b');
console.log(sum3(1, 2)); // 3let sum4 = new Function(['a,b'], 'return a + b');
console.log(sum4(1, 2)); // 3
Function函数最后一个参数永远都是函数体,由于历史原因函数的参数部分支持以逗号分割的形式展示
举例2: 一个没有参数的函数,自由函数体,没有参数的函数,在函数被调用的时候,等价于调用函数体里面的函数
const sumOfArray = new Function("const sumArray = (arr) => arr.reduce((previousValue, currentValue) => previousValue + currentValue); return sumArray",
)();// 调用函数 调用的是sumOfArray函数 但实际执行的是sumArray函数
console.log(sumOfArray([1, 2, 3, 4]))
// 10
new Function 没有参数的时候,实际上返回的是一个匿名函数(就是你传入的函数体)
解析过程
new Function的解析过程是先解析参数部分再解析函数体部分,如果参数部分有异常就会直接抛出异常,函数体就不会被执行,只有参数部分没有异常,才会解析函数体部分。这种解析方式确保了逐步验证的过程,可以防止通过传递非法参数或函数体的方式进行代码注入攻击。比如,不允许通过参数注入注释符号 /* 来破坏整个函数的结构。也就在一定程度上防止代码注入的逻辑
匿名函数
使用 new Function 后,传递的参数和函数体会被动态编译(下文会详细讲)为一个函数表达式,其编译后的代码组装方式如下
`function anonymous(${args.join(",")}
) {
${functionBody}
}`;
与普通的函数表达式不同,anonymous 这个名字不会被添加到 functionBody 的作用域中,因为 functionBody 只能访问全局作用域
anonymous 的这种编译后的组装格式,可以通过 toString() 函数查看。举个例子
const queryCondition = "return obj.age > 30 && obj.country === 'USA';";
const queryFunc = new Function('obj', queryCondition);
console.log(queryFunc.toString());
// function anonymous(obj
) {
return obj.age > 30 && obj.country === 'USA';
}
作用域
闭包是指使用一个特殊的属性 [[Environment]] 来记录函数自身的创建时的环境的函数。它具体指向了函数创建时的词法环境。
但是 new Function 创建一个函数,那么该函数的 [[Environment]] 并不指向当前的词法环境,而是指向全局环境,Function 构造函数创建的函数仅在全局作用域中执行。因此,此类函数无法访问外部(outer)变量,只能访问全局变量。
let a = 1
let fn = function () {let a = 2let result1 = new Function('console.log(a)')let result2 = function () {console.log(a)}result1() //打印出1,访问的是全局变量aresult2() //打印出2
}
fn()
// new Function这样的函数不能访问外部变量,只能访问全局变量
// 虽然这段代码可以在浏览器中正常运行,但在 Node.js 中,result1() 执行会报错,因为找不到变量 a。
// 这是因为,在 Node 中,顶级作用域不是全局作用域
严格模式下或Node中
let value2 = "芝士outer";
function getFunc() {let value = "芝士inter";let func = new Function('alert(value)');return func;
}
function getFunc2() {let func = new Function('alert(value2)');return func;
}// getFunc()(); // error: value is not defined
getFunc2()(); // error: value2 is not defined
new Function和eval的区别
与Function只能访问全局作用域不同的是,eval中的代码执行时的作用域为当前作用域。它可以访问到函数中的局部变量。
let a = 1
let fn = function () {let a = 2console.log(eval('a+8')); //10let result2 = function () {console.log(a)}result2() //打印出2
}
fn()
eval是一个危险的函数,它使用与调用者相同的权限执行代码。如果你用eval运行的字符串被 不怀好意的进行恶意修改,可能会造成全局污染或者一些不同方式的代码攻击。
eval函数通常比其他函数方法解析的更慢,因为它必须调用js解析器进行解析,而其他的函数可能被现代js引擎直接优化。
应用场景
new Function 应用场景其实还蛮多的,主要涉及的方面是动态代码执行、沙箱环境以及性能优化等。
1、动态执行代码
在一些低代码或无代码平台中,用户可能会输入自定义的 JavaScript 代码,平台需要即时执行这些代码。通过 new Function,可以将用户输入的字符串直接解析并执行。例如:
const userInput = "return a + b;";
const dynamicFunction = new Function('a', 'b', userInput);
console.log(dynamicFunction(2, 3)); // 输出 5
这种场景常见于表单计算器、在线编程环境或数据分析工具中,允许用户定义自定义的计算公式或规则。
2、模版引擎中的表达式解析
在一些模板引擎(如 Vue.js 的 v-bind、Angular 的模板表达式)中,开发者可能会通过字符串表达式绑定数据或属性。为了提高执行效率和灵活性,框架有时会通过 new Function 来生成一个能够动态计算表达式的函数。例如:
const expression = "data.a + data.b";
const compute = new Function('data', `return ${expression}`);
console.log(compute({a: 1, b: 2})); // 输出 3
通过 new Function 动态编译模板表达式,可以避免每次都对表达式重新进行解析和计算,提高性能。
3、JSONPath或XPath解析器
在数据查询场景中,像 JSONPath 或 XPath这种解析器,用户的查询条件通常是通过字符串输入的。 解析器需要根据用户输入的查询条件动态执行查询操作。这类解析器中,new Function 有时用于生成查询逻辑的动态函数,以便在大规模数据上进行快速计算和过滤。
/ 用户输入的查询条件
const queryCondition = "return obj.age > 30 && obj.country === 'USA';";
// 动态生成一个查询函数
const queryFunc = new Function('obj', queryCondition);// 用于查询的JSON数据
const data = [{ name: 'Alice', age: 35, country: 'USA' },{ name: 'Bob', age: 28, country: 'UK' },{ name: 'Charlie', age: 40, country: 'USA' }
];// 动态过滤数据
const result = data.filter(queryFunc);
console.log(result); // [{ name: 'Alice', age: 35, country: 'USA' }, { name: 'Charlie', age: 40, country: 'USA' }]
4、性能优化避免eval
new Function 与 eval 类似,可以动态执行字符串代码,但相比于 eval,new Function 的作用域更为严格。它只允许访问全局作用域,不能直接访问当前上下文的局部变量。因此,new Function 在某些需要动态执行代码的场景下比 eval 更安全,也更快,常用于替代 eval
5、表单验证或计算
在复杂的动态表单中,可能需要根据用户的输入动态生成验证规则或者计算结果。new Function 可以根据用户定义的规则生成函数,实时验证表单字段或计算结果:
const rule = "return value > 10;";
const validate = new Function('value', rule);
console.log(validate(15)); // 输出 true
6、JavaScript沙箱实现
某些框架需要隔离用户输入的代码与主应用逻辑,创建安全的沙箱环境。通过 new Function,可以限制代码的作用域,防止访问不安全的全局变量。这种方式在在线 IDE 或某些插件系统中较为常见。
new Function 不太合适的场景和弊端注意点*
在将 JavaScript 发布到生产环境之前,需要使用 压缩程序(minifier) 对其进行压缩。
压缩程序(minifier)工作原理:
- 压缩程序用于优化 JavaScript 代码,将变量名压缩成更短的名称,并删除注释、空格等无关内容。这样做能减少代码体积,提升性能。
- 压缩时,局部变量(如 let userName)会被替换为较短的变量名(如 let a),所有引用该变量的地方也会同步替换。
new Function 访问外部变量的限制
- 使用 new Function 创建的函数不会像普通函数那样能够访问外部的词法作用域(即闭包环境)。它只能访问传递给它的参数和全局变量
- 在 new Function 中,即使我们尝试引用外部定义的变量(如 userName),由于新函数的词法作用域与外部环境隔离,它是无法直接访问这些变量的
压缩程序的影响:
- 假设代码在开发时有一个变量 let userName,而你在 new Function 中尝试访问它。压缩后,userName 可能会变成 a。但 new Function 在代码压缩后才被执行,它不会知道压缩后变量名的变化,因此会导致访问出错
- 例如,如果你的代码中有:
let userName = "John"; const func = new Function("return userName;");
压缩后,userName 可能被替换为 a,但是 new Function 生成的函数依然试图访问 userName,结果会报错,因为压缩程序不会知道 new Function 中定义的内容。
正确方式:显式传递数据:
- 因为 new Function 无法访问外部变量,并且会受到压缩影响,推荐的做法是显式通过函数参数传递需要使用的数据,而不是依赖外部变量
- 例如:
let userName = "John"; const func = new Function('name', 'return name;'); console.log(func(userName)); // 这样可以正常工作 返回John
相关文章:
深入理解new Function
基础语法 let func new Function([arg1,arg2,arg3,...argN],functionBody)函数是通过使用参数 arg1…argN 和给定的 functionBody 创建。 调用 Function 时可以使用或不使用 new,两者都会创建一个新的 Function 实例 举例1: 带有两个参数的函数 let sum new Fun…...
服务器训练神经网络必备工具Screen使用教程
使用服务器训练网络时,不敢关闭终端窗口?用screen~ 服务器训练神经网络必备工具Screen使用教程 使用服务器训练网络时,不敢关闭终端窗口?用screen~一、Screen常用命令1. 启动新会话2. 重新连接会话3. 列出所有会话4. 窗口管理5. 断…...

跨越数字鸿沟,FileLink文件摆渡系统——您的数据安全高效传输新选择
在这个信息爆炸的时代,数据的流通与共享已成为推动各行各业发展的关键力量。然而,随着数据量的激增,如何在保证数据安全的前提下,实现高效、便捷的文件传输,成为了众多企业和个人用户面临的重大挑战。正是在这样的背景…...
递归之吃桃问题
题目如下: XXX买了一堆桃子不知道个数,第一天吃了一半的桃子,还不过瘾,又多吃了一个。以后他每天吃剩下的桃子的一半还多一个,到 n 天只剩下一个桃子了。XXX想知道一开始买了多少桃子。 首先我们看到题目就应该想边界…...

CZX前端秘籍2
vue生命周期( 组件从创建到销毁的过程就是它的生命周期) 创建前 beforeCreat( 在这个阶段属性和方法都不能使用) 创建时 created( 这里时实例创建完成之后, 在这里完成了数据监测, 可以使用数…...

CAD图纸防泄密用什么加密软软件?2024年10款图纸加密软件排行榜
在当今数字化时代,企业对于CAD图纸的保护越来越重视,因为图纸往往包含着公司的核心技术和商业机密。选择合适的加密软件对于防止数据泄露、维护企业利益至关重要。以下是2024年10款备受推崇的CAD图纸加密软件排行榜,帮助您更好地保护您的设计…...

WebGL编程指南 - WebGL入门
初识绘图流程、缓冲区、着色器、attribute和uniform变量 先画一个蓝色的正方形 html代码: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content&…...

mysql--数据类型
目录 搞定所有数据类型 一、常见数据类型分类 二、数值类型 1、bit类型 2、float类型 编辑3、decimal类型 4、字符类型 (1)char (2)varchar (3)varchar和char有甚区别? ࿰…...
代码随想录第40天|
#include <bits/stdc.h> using namespace std;vector<list<int>> graph; // 删除局部 graph,使用全局 graph vector<vector<int>> res; vector<int> path; int N, M;void dfs(int index) {if (index N) {res.push_back(path);…...

Turn-it:优化线材重构雕塑制造
🐨文章摘要abstract 电线雕塑在工业应用和日常生活中都很重要。 本文提出了一种新的制造策略,通过调整目标形状以适应电线弯曲机,然后由人工将其弯曲回目标形状。(机器弯曲人工弯曲) 该方法通过两阶段弯曲策略实现&a…...

微深节能 堆取料机动作综合检测系统 格雷母线
微深节能的堆取料机动作综合检测系统结合了格雷母线定位系统,是工业自动化领域的一项重要创新。该系统通过集成多种传感器和控制设备,实现对堆取料机的全面监控和精确控制,包括位置、速度、力度、振动以及工作状态等。格雷母线定位系统作为一…...

【JAVA面试题】什么是Springboot的自动配置以及注意事项
文章目录 强烈推荐核心概念:自动配置的关键特点:示例: 需要注意的点1.默认配置可能不适合所有场景2.Bean 冲突与覆盖3.应用启动慢的问题4.过度依赖自动配置5.安全性问题6.依赖冲突与版本兼容7.过多不必要的自动配置8.调试困难 专栏集锦 强烈推…...
华为鸿蒙开发笔记
记在前面 官方文档链接 因无法直接使用chatgpt进行编程(悲,2024/10),故记录笔记,方便查阅,基于arkts语言 DevEco 中文 deveco是默认有中文包的,所以在市场里面搜不错,而应该在已安装里面搜索,然后启用就行了 测试 对ts进行单独测试 打开entry/src/test/LocalUnit.test.…...

Go语言Gin框架的常规配置和查询数据返回json示例
文章目录 路由文件分组查询数据库并返回jsonservice层controller路由运行效果 启动多个服务 在 上一篇文章《使用Go语言的gorm框架查询数据库并分页导出到Excel实例》 中主要给大家分享了较多数据的时候如何使用go分页导出多个Excel文件并合并的实现方案,这一篇文章…...

JavaEE----多线程(二)
文章目录 1.进程的状态2.线程的安全引入3.线程安全的问题产生原因4.synchronized关键字的引入4.1修饰代码块4.2修饰实例方法4.3修饰静态方法4.4对象头介绍4.5死锁-可重入的特性 5.关于死锁的分析总结5.1死锁的分析5.2死锁成因的必要条件5.3死锁的解决方案 1.进程的状态 public…...

【K8S】快速入门Kubernetes
之前企业都是使用容器化和来构建自己的服务和应用程序,其中容器化优点有很多:提升了部署效率、稳定性、提高了资源的利用率降低了成本。 但是也带来了一些新的问题:容器的数量变得很多,管理就是一个新的问题。所以Kubernetes就出…...
如何在 MySQL 中处理大量的 DELETE 操作??
全文目录: 开篇语前言摘要简介概述DELETE 操作的基本概念常用的 DELETE 方法 核心源码解读简单 DELETE 语句批量 DELETE 示例 案例分析案例1:使用简单 DELETE 删除用户数据案例2:使用分批 DELETE 应用场景演示场景1:用户管理系统场…...

LabVIEW中句柄与引用
在LabVIEW中,句柄(Handle) 是一种用于引用特定资源或对象的标识符。它类似于指针,允许程序在内存中管理和操作复杂的资源,而不需要直接访问资源本身。句柄用于管理动态分配的资源,如队列、文件、网络连接、…...

【三十四】【QT开发应用】音量图标以及滑动条,没有代码补全的小技巧
效果展示 鼠标位于音量图标区域内,显示出滑动条。鼠标移出音量图标区域内滑动条隐藏。鼠标点击音量图标,如果此时音量为0,音量变成50,如果此时音量不为零,音量变为0。 CVolumeButton.h 音量图标头文件 #pragma once …...
Android修改第三方应用相机方向
以下修改基于Android7.1 diff --git a/frameworks/base/core/java/android/hardware/Camera.java b/frameworks/base/core/java/android/hardware/Camera.java index 8c7434b..7201481 100755 --- a/frameworks/base/core/java/android/hardware/Camera.java b/frameworks/ba…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...