【问题标题】:function decorator reassigning hoisted inner function without eval函数装饰器在没有评估的情况下重新分配提升的内部函数
【发布时间】:2014-06-27 15:59:42
【问题描述】:

我在玩function decorators。我想有一种方法来轻松地装饰函数不必在函数声明的地方这样做

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");

我希望能够在g 内的任何地方呼叫addDecorator。即在f 被提升到其声明上方的顶部。

在 Chrome 的控制台中,我得到以下输出:

f OUTER from outer
f OUTER from outer
f INNER from Inner (hoisted)
f INNER from Inner (after declaration)
before
f INNER from Inner (Decorated)
after
f INNER from Inner (Undecorated)
f OUTER from outer 
  1. 可以不用 eval 来完成吗?
  2. addDecorator 可以移到 g 之外吗? (不那么重要)

【问题讨论】:

  • 我不太明白你在问什么,但如果主要问题是 - 我可以在装饰应用于 f 之前在 g 顶部调用装饰 f - 我的回答没有。提升函数体在代码中的使用比分配的函数更高,但装饰是一种操作而不是声明,因此它只会在运行时序列中的那一刻发生。
  • 不,问题不在于这个。这是重新定义函数的一种非常有趣的方式——实际上,这两个问题的答案似乎都是“不”。不过还在调查。 )
  • @Brock,f 被提升到 g 的顶部,装饰被添加到 g,然后 f 被声明。没想到在调用decorator函数之前能调用decorated f。
  • 我会接受改变g 的结构或调用方式的答案,只要addDecorator 可以知道传入的函数的定义位置,因此它不必返回装饰函数被分配给原始函数的名称。即我不想拥有像f = addDecorator(d,f) 这样的代码,所以我可以制作一个可变版本:addDecorationXxToAllOf(f1, f2, f3)
  • @SamHasler:这两个问题的答案肯定都是“否”。与全局作用域不同,JavaScript 没有明确地为您提供以某种通用方式访问函数作用域的方法。因此,您可以返回新的函数值或使用对象来存储函数。请注意,上面的 instrumentFunction 也仅适用于可以访问范围的全局函数。

标签: javascript eval decorator hoisting


【解决方案1】:

如果你愿意稍微改变你的约定,你可以消除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();

http://jsfiddle.net/8SuT9/1/

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

【讨论】:

  • 我想我更愿意将我的所有函数都放在一个对象中,这样我就可以将对象柯里化地传递给 addDecorator 以避免必须执行分配。
  • @SamHasler 也是可行的。一种或另一种方式,但我相信你必须改变你的方法来实现eval的删除。
猜你喜欢
  • 2017-04-12
  • 2017-02-22
  • 1970-01-01
  • 2017-02-26
  • 1970-01-01
  • 2018-09-22
  • 2014-02-19
  • 2023-02-03
  • 1970-01-01
相关资源
最近更新 更多