美文网首页JS
深入理解Js里new Function语法

深入理解Js里new Function语法

作者: _littleTank_ | 来源:发表于2022-09-07 21:34 被阅读0次

一般我们不会使用用 new Function 构造函数的,因为没必要,直接使用 function 或者 箭头函数写法更简单。但并不是说new Function 构造函数无用。在一些特别的场景,比如函数体的数据格式是字符串的时候,new Function 构造函数的作用就显示出来了。之前也是仅仅知道此方法,但是没有具体的研究搞懂,但是最近一两年一直在倒腾低代码的项目,原理上来说,低代码都是一堆字符串,为了解析字符串就使用了new Function 构造函数(eval方法也是可以的),在此在记录一下,加深理解。详情参见:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions

1、语法

备注: 不推荐使用 Function 构造函数创建函数,因为它需要的函数体作为字符串可能会阻止一些 JS 引擎优化,也会引起其他问题。把 Function 的构造函数当作函数一样调用 (不使用 new 操作符) 的效果与作为 Function 的构造函数调用一样。

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

//等价于 let func = Function ([arg1, arg2, ...argN], functionBody);

<font color="red">Function构造函数所有的参数都是字符串类型。除了最后一个参数, 其余的参数都作为生成函数的参数即形参。这里可以没有参数。最后一个参数, 表示的是要创建函数的函数体。</font>

//传入参数
let sum = new Function('a', 'b', 'return a + b');
console.log( sum(1, 2) ); // 3

//不传入参数
let sum = new Function('console.log(1)');
console.log( sum() ); // 1

由于历史原因,new Function参数也可以以逗号分隔的列表形式给出。下边这三个声明的含义相同:

new Function('a', 'b', 'return a + b'); 
new Function('a,b', 'return a + b'); 
new Function('a , b', 'return a + b');

2、作用域

Function()构造函数和函数有一点就是:使用构造函数Function()创建的函数不使用当前的词法作用域,相反的,它们总是被顶级函数来编译,因此在运行时它们只能访问全局变量和自己的局部变量.

let a = 1
let fn = function(){
  let a = 2
  let result1 = new Function('console.log(a)')
  let result2 = function(){
    console.log(a)
  }
  result1() //打印出1,访问的是全局变量a
  result2() //打印出2
}
fn()
// new Function这样的函数不能访问外部变量,只能访问全局变量
// 虽然这段代码可以在浏览器中正常运行,但在 Node.js 中,result1() 执行会报错,因为找不到变量 a。
// 这是因为,在 Node 中,顶级作用域不是全局作用域,而 a 其实是在模块的作用域之中。

想象一下,我们必须从一个字符串创建一个函数。该函数的代码在编写脚本时是未知的,但是会在执行过程中知道。我们可能会从服务器或其他地方接收到它。此时我们的新函数需要与主脚本交互,如果它此时它可以访问外部变量,那么就可以操作外部变量,改变外部变量,这样就会引发不可预估的风险。

3、使用

假如有一个非合法 JSON 对象字符串,如下:

  let str = "{ name: '小坦克', code: 100 }" 
  JSON.parse(str) // 会报错,因为str字段是不符合规范的对象字符串(key,value都必须是"",双引号包裹)

可以使用new Function

  let str = "{ name: '小坦克', code: 100 }" 
  let result =  JSON.parse(new Function('return ' + str)()) // result = { name: '小坦克', code: 100 }

4、new Function和eval的区别

eval中的代码执行时的作用域为当前作用域。它可以访问到函数中的局部变量。

let a = 1
let fn = function(){
  let a = 2
  let result1 = new Function('console.log(a)')
  let result2 = eval('console.log(a)') //打印出2
  result1() //打印出1,访问的是全局变量a
}
fn()

永远不要使用 eval !!!

eval() 是一个危险的函数, 它使用与调用者相同的权限执行代码。如果你用 eval() 运行的字符串代码被恶意方(不怀好意的人)修改,您最终可能会在您的网页/扩展程序的权限下,在用户计算机上运行恶意代码。更重要的是,第三方代码可以看到某一个 eval() 被调用时的作用域,这也有可能导致一些不同方式的攻击。相似的 Function 就不容易被攻击

eval() 通常比其他替代方法更慢,因为它必须调用 JS 解释器,而许多其他结构则可被现代 JS 引擎进行优化。

此外,现代 JavaScript 解释器将 JavaScript 转换为机器代码。这意味着任何变量命名的概念都会被删除。因此,任意一个 eval 的使用都会强制浏览器进行冗长的变量名称查找,以确定变量在机器代码中的位置并设置其值。另外,新内容将会通过 eval() 引进给变量,比如更改该变量的类型,因此会强制浏览器重新执行所有已经生成的机器代码以进行补偿。但是(谢天谢地)存在一个非常好的 eval 替代方法:只需使用 window.Function。这有个例子方便你了解如何将eval()的使用转变为Function()。

相关文章

  • 深入理解Js里new Function语法

    一般我们不会使用用 new Function 构造函数的,因为没必要,直接使用 function 或者 箭头函数写...

  • js new 运行机制

    js手札--js中new到底做了些啥JS核心系列:理解 new 的运行机制深入理解 Javascript 运行机制及原型

  • A26-JS函数

    Function -MDN 语法:new Function ([arg1[, arg2[, ...argN]],]...

  • 深入理解JS 中原型和原型链

    JS 中原型和原型链深入理解 首先要搞明白几个概念: 函数(function) 函数对象(function obj...

  • 关于js原型Prototype的理解

    深入理解可参考首先说下什么是js原型:  js每声明一个function,都有prototype原型,protot...

  • js 里面的 function 与 Function

    function 是 js 的标识符 Function 是 js 里面的一个 构造函数 1、new functio...

  • HTML web shell使用

    js function Run(strPath){try{var objShell = new ActiveXO...

  • js格式化日期

    //js获取定制格式日期function getFormatDate() {var nowDate = new D...

  • js 深入

    * js语法* js的动态函数和匿名函数* js动态函数Functionnew Function();* 匿名函数...

  • JS补充3

    JS的基本语法 JS语句基本规则 语句后面要用分号结束,特例:function,for, if后面...

网友评论

    本文标题:深入理解Js里new Function语法

    本文链接:https://www.haomeiwen.com/subject/lgqnnrtx.html