【问题标题】:NodeJS: runInNewContext and instanceofNodeJS:runInNewContext 和 instanceof
【发布时间】:2012-11-07 15:40:00
【问题描述】:

我有一个这样的脚本:

var context = {}
vm.runInNewContext("var someFunc = function() {}", context);
console.log(typeof context.someFunc); //function
console.log(context.someFunc instanceof Function); //false

我明白为什么第 4 行返回 false:在新上下文中有一个新的 Function 对象,它不等于外部上下文中的 Function 对象。因此,context.someFunc 不是该外部 Function 对象的实例。

但是,context.someFunc 函数由使用 instanceof Function 的第三方库使用。由于context.someFunc 是一个函数,而不是Function 在该上下文中的实例,因此第三方不会将其视为函数,因此它应该崩溃。我尝试使用以下上下文:

var context = {
    "Function" : Function
}

但这也没有解决我的问题。

也许使用var someFunc = new Function(arg, body) 会起作用(尚未测试),但是我无法完全控制传递给vm.runInNewContext 的代码,因此我也无法使用该解决方案。

如何让context.someFunc instanceof Function 在上下文之外返回 true?

【问题讨论】:

    标签: node.js instanceof


    【解决方案1】:

    这是不可能的。在您无法控制第三方模块的情况下使用相同的上下文。当我遇到类似问题时,首先我尝试修复第三方模块并提交拉取请求并解释问题所在,然后我放弃并切换到 new Function() 中的 eval 而不是在新上下文中运行,这更适合满足我的需求。

    【讨论】:

      【解决方案2】:

      确实存在解决方案,但需要在完整性和性能之间进行权衡。

      1. 只需将返回的函数包装在另一个函数中:

         const context = {}
         vm.runInNewContext("var someFunc = function() {}", context);
         const someFunc = context.someFunc;
         context.someFunc = function(...args) { return someFunc.apply(this, args); }
         console.log(context.someFunc instanceof Function); //true
        

        此解决方案(几乎)没有开销,但它不是一个完整的解决方案。它适用于直接在上下文中公开的已知函数,但在不太琐碎的情况下它开始崩溃。例如。让它与高阶函数、地图等一起工作需要相当多的工作,我认为甚至不可能涵盖所有奇异的组合。

      2. 使用Proxy 按需包装函数

        使用Proxy,不需要提前知道context 上公开了哪些值,而是可以按需包装函数。这也使得处理高阶函数变得更容易,因为我们可以递归地代理返回值和参数。然而,正确实施需要付出更多努力,并且会对性能产生重大影响。

      3. 在新上下文中更改 Function 原型

        const context = { OuterFunction : Function};
        vm.runInNewContext(`
          // setup
          Object.setPrototypeOf(Function.prototype, OuterFunction.prototype);
          //script
          const someFunc = function() {};
        `, context);
        console.log(context.someFunc instanceof Function);
        

        此解决方案使内部Function 扩展外部Function,因此任何内部函数都是外部函数的实例。但是,使用setPrototypeOf 对性能非常不利,尤其是在更改像Function 这样的对象时。因此,应尽可能避免这种情况。

      【讨论】:

        猜你喜欢
        • 2015-02-22
        • 1970-01-01
        • 1970-01-01
        • 2011-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多