使用另一个文件中的模板字符串评估JS文件

时间:2017-06-22 14:51:36

标签: javascript ecmascript-6 eval

我想使用Electron webContents API中名为executeJavaScript()的函数。由于它非常接近eval(),我将在示例中使用它。

问题:

  • 我有一个体面的大小脚本,但它包含在模板字符串中。
  • 扩展此应用程序,脚本可能会以字符串形式增长。
  • 我不确定最佳做法是什么。

我也理解eval()很危险,但我对我的问题的原则感兴趣。

我的问题的基本评估示例:

// Modules
const fs = require('fs');

// CONSTANTS
const EXAMPLE_1 = 'EXAMPLE_1';
const EXAMPLE_2 = 'EXAMPLE_2';
const EXAMPLE_3 = 'EXAMPLE_3';

const exampleScriptFunction = require('./exampleScriptFunction');
const exampleScriptFile = fs.readFileSync('./exampleScriptFile.js');

// using direct template string
eval(`console.log(${EXAMPLE_1})`);

// using a method from but this doesnt solve the neatness issue.
eval(exampleScriptFunction(EXAMPLE_2));

// What I want is to just use a JS file because it is neater.
eval(`${exampleScriptFile}`);

exampleScriptFunction.js

module.exports = function(fetchType) {
  return `console.log(${fetchType});`;
}
  • 这将允许我将脚本分离到新文件
  • 如果我有多于1个变量???
  • 怎么办?

exampleScriptFile.js:

console.log(${EXAMPLE_3});
  • 这显然不起作用,但我只想表达自己的想法。
  • 后退标记不存在,fs加载为字符串,主文件有后退标记。
  • 这不起作用。我不知道怎么表达我的意思。
  • 因为我正在加载这将是readFileSync,我认为es6模板字符串可以工作。
  • 这允许我编写一个带有正确语法高亮显示的普通js文件
  • 问题是变量在运行eval()的页面上。

也许我在这里完全错了,看错了方法。我愿意接受建议。因为我在编程方面没有兴趣,请不要标记我减1。我真的不知道怎么回答这个问题。谢谢。

2 个答案:

答案 0 :(得分:1)

假设您的来源存储在exampleScriptFile



// polyfill
const fs = { readFileSync() { return 'console.log(`${EXAMPLE_3}`);'; } };

// CONSTANTS
const EXAMPLE_1 = 'EXAMPLE_1';
const EXAMPLE_2 = 'EXAMPLE_2';
const EXAMPLE_3 = 'EXAMPLE_3';

const exampleScriptFile = fs.readFileSync('./exampleScriptFile.js');

// What I want is to just use a JS file because it is neater.
eval(exampleScriptFile);




更新

也许我不清楚。 ./exampleScriptFile.js应为:

console.log(`${EXAMPLE_3}`);

答案 1 :(得分:0)

虽然@PatrickRoberts演示的eval可以完成您的描述,但不会扩展到executeJavaScript

前者在调用者的上下文中运行,而后者使用代码的内容触发对另一个进程的IPC调用。据推测,此过程没有关于调用者上下文的任何信息,因此,模板字符串不能填充在此上下文中定义的变量。

来自electron/lib/browsers/api/web-contents.js的相关摘要:

WebContents.prototype.send = function (channel, ...args) {
  // ...
  return this._send(false, channel, args)
}

// ...

WebContents.prototype.executeJavaScript = function (code, hasUserGesture, callback) {
  // ...
  return asyncWebFrameMethods.call(this, requestId, 'executeJavaScript',
  // ...
}

// ...

const asyncWebFrameMethods = function (requestId, method, callback, ...args) {
  return new Promise((resolve, reject) => {
    this.send('ELECTRON_INTERNAL_RENDERER_ASYNC_WEB_FRAME_METHOD', requestId, method, args)
    // ...
  })
}

来自electron/atom/browser/api/atom_api_web_contents.cc

的相关摘录
//...
void WebContents::BuildPrototype(v8::Isolate* isolate,
                                 v8::Local<v8::FunctionTemplate> prototype) {
  prototype->SetClassName(mate::StringToV8(isolate, "WebContents"));
  mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
      // ...
      .SetMethod("_send", &WebContents::SendIPCMessage)
      // ...
}