基于一次性的自定义函数模式
On a one-time self-re-defining function pattern
考虑以下模式:
function foo /* aka outer_foo */ () {
// === stage 1 ===
// declaration and initialization of closure variables
var ... <CLOSURE_VARS> ...;
// initialization of CLOSURE_VARS
// (possibly expensive and/or depending on values known only at run-time)
// === stage 2 ===
// one-time redefinition of foo
foo = function /* inner_foo */ ( arg0, ... ) {
var results;
// code computing value of results based on CLOSURE_VARS, arg0, ...
// foo is never modified here
return results;
};
// === stage 3 ===
// invocation of inner function and returning of result
return foo.apply( this, arguments );
}
为方便起见,我将使用术语outer_foo和inner_foo分别表示上面的外部和内部函数,尽管代码不使用这些标识符。
outer_foo的主体包括三个阶段(后两个阶段各由一条语句组成):- 一些闭包变量的声明和初始化;
- 标识符
foo
的重新定义; - 将最初传递给outer_foo的参数传递给inner_foo,并返回结果。
outer_foo函数体将最多执行一次,即第一次执行名为"foo
"的函数。被调用,如果它发生的话。从今以后,outer_foo的函数体将不可访问,随后所有对名为foo
的函数的调用都将不可访问。将导致执行inner_foo。
一般来说,人们可以设想这种模式的一些变化1,但是我在这里谈论的基本模式的基本约束是:
-
foo
在执行outer_foo
2; -
foo
在inner_foo
的执行过程中不会被重新定义。
(如果违反了这些基本约束,所有的赌注都是无效的;这种情况不在这个问题的范围之内。
我已经意识到这个方案的至少一个缺点:一些实践者认为自定义函数令人困惑,不利于代码的可读性,和/或本质上很差,即使重新定义只以完全确定的方式发生一次,就像上面的方案中的情况一样。
我的问题是:该方案是否有任何额外的缺点,如果有,它们是什么?
我对JavaScript特有的缺点特别感兴趣。
1例如
function foo /* aka outer_foo */ () {
var inner_foo, ... <CLOSURE_VARS> ...;
if ( some_deterministic_test() ) {
inner_foo = function ( arg0, ... ) {
// etc.
}
}
else {
inner_foo = function ( arg0, ... ) {
// etc.
}
}
foo = inner_foo;
return foo.apply( this, arguments );
}
在这个变体中,最终分配给foo
的函数取决于在运行时执行的一些测试。
2这里很容易规定,foo
不仅必须在outer_foo中精确地重新定义一次,而且必须"确定地"重新定义。当然,任何对"确定性"的偏离foo
的最终设置只会增加代码运行时行为的复杂性。不幸的是,我不知道如何在不陷入律师细枝碎节的迷宫的情况下使这一规定准确无误。我能做的最好的事情就是加上"越确定越好"这句模棱两可的短语,希望读者能明白我的意思。然而,这个额外规定的唯一效用是排除不正当的,但完全不现实的场景(例如,foo
的最终值取决于随机过程的结果),所以我把它省略了。
我还能想到两点你应该注意:
- 性能strong>。编译器就像你提到的那些人。他们中的一些人会对这种模式感到困惑,他们可能无法像使用不同的模式那样对其进行优化。这可能是一个问题,也可能不是,但你应该确保测试它。 <
- 打破合同/strong>。您说希望outer_foo最多执行一次。事实可能并非如此!有人可能会传递它并在某处放置对它的引用,这样在被调用时它就不会变得不可访问。当然,这是不可能的,但根据您的需求,您可能想要防止它。
毕竟,这是一种失败的设计,因为仅仅是一个别名 (var f = foo; f()
)不应该改变功能。确保所有消费者/用户都知道你在做什么,这样他们就不会被绊倒。
- 自定义函数中的光标位置
- Google Sheet自定义函数返回0
- 其中是自定义函数中的属性
- 创建自定义函数以在函数上运行完整的多选下拉列表
- Google Sheets自定义函数条件格式
- dalek回调或自定义函数
- UI网格:如何从自定义函数访问MODEL_COL_FIELD
- 评估作为参数传递给 Google 电子表格中自定义函数的条件
- 具有自定义函数调用的 HTML 表单
- 使用 jQuery 对动态创建的元素调用自定义函数
- 从自定义函数返回promise
- extjs-使用传递的参数创建自定义函数
- 自定义URL模式
- AngularJS DI用于自定义函数
- Javascript 自定义函数错误
- 如何使用Angular 1.5组件将属性求值为字符串,这是一个自定义函数
- 为谷歌工作表创建一个自定义函数
- Angular2 在创建 ngSwitch 新视图后调用自定义函数
- JavaScript自定义函数返回意外值
- 基于一次性的自定义函数模式