eval与new Function的区别

1、简介

eval和new Function均可以将一段字符串解析成一段JS脚本并执行javascript

2、eval和 new Function的使用

① eval: java

eval做为一个方法,直接传入要解析的字符串便可app

const foo = "foo"; // 定义了一个变量foo
const str = "console.log(foo)";
eval(str); // 解析str字符串中包含JS脚本并执行,输出foo

② new Function:
JS中的每一个函数都是 Function 类型的实例,即JS中全部的函数的proto都指向Function的prototype,或者说,JS中全部的函数都是由Function构造出来的函数

new Function() 能够接n个参数,最后一个参数做为函数体this

let func = new Function ([arg1[, arg2[, ...argN]],] functionBody);
let foo = new Function("name", "console.log(name)");
// 建立的函数指向Function的原型
console.log(foo.__proto__ === Function.prototype); // true

// 等价于
function foo(name) {
    console.log(name);
}

能够看到Function的最后一个参数字符串"console.log(name)"也被解析成了JS脚本,而且做为函数体执行了prototype

须要注意的是,传入的字符串不是任意的,必须是能当作JS脚本正常执行的字符串code

const str = "{'foo': '123'}";
const obj = eval(str);
console.log(obj);
// 报错信息以下
VM1061:1 Uncaught SyntaxError: Unexpected token ':'
    at <anonymous>:2:18

由于传入"{'foo': foo}"的时候,{}会被解析为代码块,至关于直接执行const str = "'foo': foo";解决方法能够在外层加上一个括号,如:token

const str = "({'foo': '123'})";
const obj = eval(str);
console.log(obj);// {foo: '123'}

3、eval和new Function的区别

eval中的代码执行时的做用域为当前做用域它能够访问到函数中的局部变量
new Function中的代码执行时的做用域为全局做用域不论它的在哪一个地方调用的它访问的都是全局变量ip

let foo = "foo";
function bar() {
    let foo = "bar";
    eval("console.log(foo)"); // 输出bar
    new Function("console.log(foo)")(); // 输出foo
}
bar();

从输出结果能够看出,new Function访问到的始终是全局做用域中的变量;eval访问到的则是当前做用域中的变量
固然若是使用的是window.eval()或者global.eval()那么访问到的也始终是全局做用域中的变量作用域

let foo = "foo";
function bar() {
    let foo = "bar";
    window.eval("console.log(foo)"); // 输出foo
    new Function("console.log(foo)")(); // 输出foo
}
bar();

此时输出都是foo了
若是全局做用域中没有指定的变量,那么将会报错,提示该变量没有定义

function bar() {
    let foo = "bar";
    window.eval("console.log(foo)"); // 报错
    new Function("console.log(foo)")(); // 报错
}
bar();
// 报错信息以下
VM1051:1 Uncaught ReferenceError: foo is not defined
    at eval (eval at bar ((index):3), <anonymous>:1:13)
    at eval (<anonymous>)
    at bar (<anonymous>:3:12)
    at <anonymous>:6:1

4、使用场景

在Vue生成渲染函数的时候会使用到,Vue中进行模板编译的时候,最终会将模板编译成一段可执行JS字符串,而后传递给new Function生成渲染函数,渲染(挂载)的时候,执行这个渲染函数拿到对应的虚拟DOM节点,如:

// template模板
<div id="app" style="color: red;background: blue;"><p>hello {{name}}</p>{{msg}}</div>
// 解析模板生成一段字符串,即渲染函数要执行的字符串
let code = _c("div", {id: "app",style: {"color":" red","background":" blue"}},_c("p", undefined,_v("hello"+_s(name))),_v(_s(msg)))
// 将渲染函数要执行的字符串传入new Function()生成渲染函数
let renderFn = new Function(`with(this) {return ${code}}`);

等到渲染的时候,就会执行渲染函数,即renderFn(),此时就会执行code所指的字符串,拿到对应的虚拟DOM节点,进行patch最终更新真实的DOM节点。

相关文章
相关标签/搜索