ES6中的Javascript`eval()`范围

fra*_*eco 7 javascript ecmascript-6

我正在一个Foo1名为的实例上动态创建一个函数test.我正在使用创建此功能eval.我希望这个函数可以访问Foo2类,但是我得到了一个ReferenceError: Foo2 is not defined.

我已经解决了这个问题,Babel可以在这里找到

如果您想自己运行示例代码,请从此处下载并按照README.MD重现中的说明进行操作.

跑步:

npm install
npm run start
naviage to localhost:8080

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

root
  - src
    - Foo1.js
    - Foo2.js
  - .babelrc
  - app.js
  - package.json
Run Code Online (Sandbox Code Playgroud)

Foo1.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();');
    }
}
Run Code Online (Sandbox Code Playgroud)

Foo2.js

export default class Foo2 {

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

}
Run Code Online (Sandbox Code Playgroud)

.babelrc

{
  "presets": ["es2015"]
}
Run Code Online (Sandbox Code Playgroud)

app.js

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);
Run Code Online (Sandbox Code Playgroud)

的package.json

{
    "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"
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我将Foo2.js类更改为以前版本的javascript,一切都像魅力:

function Foo2() { }

Foo2.prototype.test = function() {
    console.log('i\'m working!');
};

module.exports = Foo2;
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 6

看起来你的代码被封装在一个模块中.模块中的顶级声明不是全局声明,但正如您所发现的那样,创建的函数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 + "})");
  }
})();
Run Code Online (Sandbox Code Playgroud)

让我重申使用的问题eval,只是要非常清楚

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

  • 使用eval在执行方面基本上就不可能了JavaScript引擎优化在这方面的代码,所以,如果你能包含的问题,它孤立的小功能