ES6中的Javascript`eval()`范围

时间:2016-07-29 15:46:05

标签: javascript ecmascript-6

我正在名为Foo1的{​​{1}}实例上动态创建一个函数。我正在使用test创建此功能。我希望此函数可以访问eval类,但我得到的是Foo2

我已经向ReferenceError: Foo2 is not defined提出了有关此问题的问题,可以找到here

如果您想自己运行示例代码,请从here下载并按照Babel中的说明重现。

运行:

npm install
npm run start
naviage to localhost:8080

以下是我环境中的Minimal,Complete和Verifiable示例的目录结构:

README.MD

Foo1.js

root
  - src
    - Foo1.js
    - Foo2.js
  - .babelrc
  - app.js
  - package.json

Foo2.js

import Foo2 from './Foo2.js';

export default class Foo1 {
    constructor() {
        // Isolate the impact of eval within makeFunction
        let makeFunction = text => {
            return eval("(function() { " + text + "})");
        };
        this.test = makeFunction('let foo2 = new Foo2(); foo2.test();');
    }
}

.babelrc

export default class Foo2 {

    test() {
        console.log('i\'m working!');
    }

}

app.js

{
  "presets": ["es2015"]
}

的package.json

import express from 'express';
import http from 'http';
import Foo1 from './src/Foo1.js';

const app = express();
const server = http.createServer(app);

app.get('/', (req, res) => {
    let test = new Foo1();
    test.test();

    res.end('bye');
});

server.listen(8080);

现在,如果我将{ "name": "test", "scripts": { "start": "./node_modules/babel-cli/bin/babel-node.js ./app.js" }, "dependencies": { "http": "*", "express": "*", "babel-cli": "^6.7.7", "babel-core": "^6.7.7", "babel-polyfill": "^6.3.14", "babel-preset-es2015": "^6.6.0" } } 类更改为以前版本的javascript,一切都像魅力一样:

Foo2.js

2 个答案:

答案 0 :(得分:6)

看起来你的代码被封装在一个模块中。模块中的顶级声明是 not globals,但正如您所发现的,使用new Function创建的函数不会在创建它们的上下文中关闭;它们的创建好像它们处于全球范围。

正如您所指出的那样,new Function并不理想,因为它提供了对任意代码的评估,但如果您控制并且可以信任您正在评估的代码,则不是一定是个问题。 new Function的存在也极大地破坏了JavaScript引擎优化代码所在的能力(因为它无法知道函数文本中的内容),所以如果可以,最好保持这些相当孤立。

由于new Function已经存在这两个问题,我们可以继续使用eval,它们共享它们:eval适用于当前范围,而不是全局范围。

eval示例:

// Scoping function so we know for sure we're not creating globals
(function() {
  var foo = "bar";
  
  var algorithm = "console.log(foo);";
  var f = makeFunction(algorithm);
  f();
  
  // Isolate the impact of eval within makeFunction
  function makeFunction(text) {
    return eval("(function() { " + text + "})");
  }
})();

让我重申使用eval的问题,只是为了清楚

  • 重要的是,您只能eval代码信任

  • 在执行上下文中使用eval基本上使JavaScript引擎无法优化该上下文中的代码,因此如果您能够控制该问题,请将其隔离为小函数

答案 1 :(得分:0)

之所以不起作用,是因为您使用babel来转换代码,从而将import Foo2和对Foo2的所有引用更改为某种对象属性访问。但是它不能更改您的评估代码,因为它仅在运行时才知道,而在构建时才知道,因此Foo2保持不变且无效。