解析javascript函数中用于序列化的外作用域引用

Resolving outer-scope references in a javascript function for serialization

本文关键字:作用域 引用 序列化 用于 javascript 函数 解析      更新时间:2023-09-26
var foo = (function(){
  var x = "bar";
  return function(){
    console.log(x);
  };
})();
console.log(foo.toString()); // function() {console.log(x);}
(foo)(); // 'bar'
eval('(' + foo.toString()+')()')); // error: x is undefined

是否有一种解析(修改)函数的技术,使外部作用域的引用成为局部引用,如:

function() {console.log(x);}

就变成:

function() {console.log("bar");}

该函数现在可以被字符串化并在网络上传输,并在另一个运行时执行。

也许可以解析函数到抽象语法树,然后修改它?引用总是在作用域之外(不可用),对吗?

目的:

我正在序列化一个从节点运行时到postgresql plv8运行时的过滤器函数。现在过滤器函数有一个接口:dbClient。Filter ((row, age) => row。age> age), ageFromOuterScope)。Then (matches =>…)

我想要接口dbClient.filter((row) => row。Age> Age))。然后(matches =>…),其中age是来自外部作用域的引用。

更新:

我只能想到一个解决办法。分析函数,检测对函数外部变量的引用,然后重写原始函数:

function(row) {
   return row.age > age
}

:

function(row, age) {
  return row.age > age
}

检测到的变量也应该添加到表示数组的字符串中,如:

var arrayString = '[age]'

然后求出字符串:

var functionArgs = eval(arrayString)

最后:

dbClient.filter(modifiedFunction, ...functionArgs).then(matches => ...)

要在作用域外公开私有变量,需要在作用域内的另一个函数重写toString返回的方法描述。然后使用该函数而不是toString来检索方法描述。

var foo = (function(){
  var x = "bar";
  var f = function(){
    console.log(x);
  };
  f.decl = function() {
      return f.toString().replace("(x)", "('""+x+"'")");
  }
  return f;
})();
console.log(foo.decl()); // function() {console.log("bar");}
eval("("+foo.decl()+")()"); // bar

我通过Google的闭包编译器运行了你的top codebox's foo,它给了我这个:

var foo=function(){return function(){console.log("bar")}}();foo;

不完全是你想要的,但你可以使用eval()和/或toString()从那里得到你想要的,因为你已经在修补了。

我不知道这有多健壮,它使其他代码混乱,但对于您所展示的简单函数,它似乎始终内联出现在代码中的非重复原语。

可以将x绑定到函数对象本身。

var foo = (function(){
  var x = "bar";
  return function(){
    this.x = x;
    console.log(this.x);
  };
})();
(foo)() // 'bar'
console.log(foo.toString()); // 'function() { this.x = x; console.log(this.x) }'
eval('(' + foo.toString()+')()'); // 'bar'