【发布时间】: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
- 可以不用 eval 来完成吗?
- 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