Javascript 功能装饰器重新分配提升的内部功能,无需评估

Javascript 功能装饰器重新分配提升的内部功能,无需评估,javascript,eval,decorator,hoisting,Javascript,Eval,Decorator,Hoisting,我在和你玩。我希望有一种方法可以轻松地装饰函数,而不必在声明函数的地方进行装饰 var __slice = [].slice; this.around = function(decoration) { return function(base) { return function() { var argv, callback, __value__, _this = this; argv = 1 <= argume

我在和你玩。我希望有一种方法可以轻松地装饰函数,而不必在声明函数的地方进行装饰

var __slice = [].slice;

  this.around = function(decoration) {
    return function(base) {
      return function() {
        var argv, callback, __value__,
          _this = this;
        argv = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        __value__ = void 0;
        callback = function() {
          return __value__ = base.apply(_this, argv);
        };
        decoration.apply(this, [callback].concat(argv));
        return __value__;
      };
    };
  };

f("from outer");
function f(a){
  console.log("f OUTER",a);
};
f("from outer");
(function g(){
  f("from Inner (hoisted)");


function addDecorator(decoration, fn) {
  var decorated = around(decoration)(fn);
  eval(fn.name + " = decorated");
  decorated.unDecorate = function (){
    eval(fn.name + " = fn");
  }
}

  function myDecorator(cb){
      console.log("before");
      cb();
      console.log("after");
    }


  function f(a){
    console.log("f INNER",a);
  }

  f("from Inner (after declaration)");
  addDecorator(myDecorator, f);

  f("from Inner (Decorated)");
  f.unDecorate();
  f("from Inner (Undecorated)");
})();
f("from outer");
  • 这可以不用评估吗
  • addDecorator可以移到g之外吗?(不那么重要)

  • 如果您愿意稍微更改约定,您可以消除
    eval
    并将函数移到
    g
    之外

    这将具有相同的效果,但名称略有不同:

    function addDecorator(decoration, fn) {
        var decorated = around(decoration)(fn);
        decorated.unDecorate = function () {
            return fn;
        }
        return decorated;
    }
    
    f = addDecorator(myDecorator, f);
    
    f = f.unDecorate();
    


    如果您不愿意改变它的命名/使用方式,那么恐怕您的两个问题的答案都是否定的。

    我不太明白您的问题,但如果主要问题是-在装饰应用于
    f
    之前,我是否可以在
    g
    顶部调用装饰的
    f
    -我的答案是否定的。提升会使功能体在代码中的使用高于分配的功能,但装饰是一种操作,而不是一种声明,因此,它只会在运行时序列中的某一时刻发生。不,问题不在于此。这是一种非常有趣的重新定义函数的方法——实际上,这两个问题的答案似乎都是“否”。不过,仍在调查中。)@Brock,f被提升到g的顶部,装饰被添加到g,然后f被声明。在调用decorator函数之前,我不希望能够调用decordeator f。只要能让
    addDecorator
    知道传入函数的定义位置,从而不必返回要分配给原始函数的修饰函数,我将接受更改
    g
    的结构或调用方式的答案函数的名称。i、 e.我不想要像
    f=addDecorator(d,f)
    这样的代码,所以我可以制作一个varadic版本:
    addDecorationXxToAllOf(f1,f2,f3)
    @SamHasler:这两个问题的答案肯定是“不”。与全局作用域不同,JavaScript显式地不提供以某种通用方式访问函数作用域的方法。因此,您可以返回新函数值,也可以使用对象存储函数。请注意,上面的
    instrumentFunction
    也只适用于可以访问作用域的全局函数。我想我更愿意将我的所有函数放在一个对象中,这样我就可以将对象传递给addDecorator,以避免必须进行赋值。@SamHasler也是可行的。不管怎样,我相信你必须改变你的方法来去除
    eval
    function addDecorator(decoration, fn) {
        var decorated = around(decoration)(fn);
        decorated.unDecorate = function () {
            return fn;
        }
        return decorated;
    }
    
    f = addDecorator(myDecorator, f);
    
    f = f.unDecorate();