繁体   English   中英

ES6 中的 JavaScript `eval()` 作用域

[英]Javascript `eval()` scope in ES6

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

我已经向Babel提出了一个关于这个的问题,可以在这里找到

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

跑步:

npm install
npm run start
naviage to localhost:8080

以下是我的环境中最小、完整和可验证示例的目录结构:

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

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();');
    }
}

Foo2.js

export default class Foo2 {

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

}

.babelrc

{
  "presets": ["es2015"]
}

应用程序.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);

包.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"
    }
}

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

function Foo2() { }

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

module.exports = Foo2;

看起来您的代码被封装在一个模块中。 模块中的顶级声明不是全局变量,但正如您所发现的,使用new Function创建的new Function不会在创建它们的上下文中关闭; 它们的创建就好像它们在全局范围内一样。

正如您所指出的, new Function并不理想,因为它提供了对任意代码的评估,但是如果控制并可以信任您正在评估的代码,那不一定是问题。 new Function的存在也大大削弱了 JavaScript 引擎优化代码出现位置的能力(因为它无法知道函数文本中的内容),所以如果可以的话,最好将它们保持相当隔离。

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

eval示例:

 // Scoping function to fake the effect of module scope (function() { let foo = "bar"; let algorithm = "console.log(foo);"; let fn = makeFunction(algorithm); fn(); // Isolate the impact of eval within makeFunction function makeFunction(text) { return eval("(function() { " + text + "})"); } })();

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM