2

我正在尝试在 TypeScript 中创建一个动态函数,该函数调用一个已经存在的函数,例如:

let dynamicFunction = new Function("existingFunction(\"asdf\");");

function existingFunction(name: string) {
    console.log(name);
}

在 chrome dynamicFunction 中调试时看起来像这样:

(function() {
existingFunction("asdf");
})

当我尝试执行 dynamicFunction 时,它显示“未捕获的 ReferenceError:existingFunction 未定义”,这并不奇怪,因为它是一个不同的范围,但我如何才能在 dynamicFunction 中实际调用exisitingFunction?

任何帮助将不胜感激!

编辑:

更准确地说:我有一个包含一个模块的打字稿文件。此模块导出一个函数,该函数应返回创建的动态函数。然后在另一个实际包含现有函数的模块中使用创建的动态函数。

我选择这种方法是因为我需要将给定的字符串转换为可执行条件,该条件将被执行多次。

例如:将字符串“VALUE==1”转换为:

function () {
    return exisitingFunction("VALUE") == 1;
}

它应该是什么样子的一个简短示例:

解析器.ts:

export module Parser {
   export function getFunction(expression: string) {
      // Calculating condition...
      let condition = "existingFunction(\"VALUE\") == 1;"
      return new Function(condition);
   }
}

条件.ts:

import { Parser } from "./parser";
class Condition {
    // getting the DynamicFunction
    private _dynamicFunction = Parser.getFunction("VALUE==1");

    someFunctionInsideCondition() {
       // Calling the DynamicFunction
       this._dynamicFunction();
    }
}

// Maybe this function should be somewhere else?
function existingFunction(name: string) {
    console.log(name);

    return 1;
}

我希望这能更好地解释我的问题。

4

2 回答 2

1

来自函数文档

使用 Function 构造函数创建的函数不会为其创建上下文创建闭包;它们总是在全局范围内创建。运行它们时,它们将只能访问自己的局部变量和全局变量,而不能访问调用 Function 构造函数的范围内的变量。这与将 eval 与代码用于函数表达式不同。

所以你必须existingFunction作为参数传递或在全局空间中定义它。

尝试

var existingFunction = function(name: string) {
    console.log(name);
}

还可以查看eval哪些可以让您访问当前范围...

- - 更新

在问题更新并考虑您关于出于安全考虑而不想使用 eval 的评论之后(我完全同意)

问题是在生成函数的范围内,thisundefined. 让你existingFunction成为全局范围的一部分已经是一个坏主意,并且在 Typescript 和模块架构之间似乎根本不可能。

那么为什么不将上下文传递给生成的函数呢?

这将允许您控制要向生成的函数公开多少应用程序,同时允许它访问外部方法。

类似于以下内容:

class Parser {
    static getFunction(expression) {
        let condition = new Function("context", "context.existingFunction(\"VALUE\") == 1;");
        return condition;
    }
}

class Condition {
    constructor() {
        this._dynamicFunction = Parser.getFunction("VALUE==1");
    }

    someFunctionInsideCondition() {
        // Calling the DynamicFunction
        this._dynamicFunction(this);
    }

    existingFunction(name) {
        console.log("hello " + name);

        return 1;
    };
}



let c = new Condition();
c.someFunctionInsideCondition();

当然,您context可以是一个不同的对象,而不是 ,您可以在this其中保留所有实用程序功能。

我不得不将(编译下来,我自己的话)到 es2015 以使示例在此处运行,但我最初是在 Typescript 中制作的并且工作正常

于 2016-12-21T11:55:35.093 回答
0

我会跳过使用,new Function而是按如下方式进行。

parser.ts文件将包含以下内容:

export class FunctionGenerator {
    constructor(private fn: Function) {}

    makeFunction(args: string): Function {
        const [variable, val] = args.split("==");
        return () => this.fn(variable) == val;
    }
}

这基本上是一个工厂,它允许创建一系列函数,这些函数调用工厂创建时传递的函数。然后,您可以将其makeFunction用于您要执行的特定检查。(请注意,我在您的问题中使用了like。除非有反对的理由,否则==我更喜欢使用。)===

然后可以像这样使用它:

import * as parser from "./parser";

let vars = {};

// This is a simulation of your funciton. It just plucks values from `vars`.
function existingFunction(name: string) {
    return vars[name];
}

function resetVars() {
   vars = {
    "VALUE": 1,
    "FOO": 2,
    "BAR": 3,
   };
}

function test(gen) {
    const fn1 = gen.makeFunction("VALUE==1");
    console.log(fn1(), "should be true");

    const fn2 = gen.makeFunction("BAR==3");
    console.log(fn2(), "should be true");

    vars["BAR"] = 7;
    // Call the same function again, but with a new value in `vars`.
    console.log(fn2(), "should be false");

    const fn3 = gen.makeFunction("BAR==1000");
    console.log(fn3(), "should be false");
}

resetVars();
const gen = new parser.FunctionGenerator(existingFunction);
test(gen);
于 2016-12-21T17:50:04.887 回答