我正在为我的开发团队编写一个javascript样式指南,并尝试引入一些命名约定。
为了避免嵌套闭包,我在指南中添加了一条规则,即编写闭包工厂而不是嵌套它(并在根级别编写命名回调而不是嵌套它)。它允许展平函数定义并将最大嵌套级别设置为2。
例如,而不是:
function main (userName) {
var foo = ['bar', 'baz']
foo.forEach(function (item) {
console.info(userName + ' add the ' + item + 'event listener')
document.addEventListener(item, function (evt) {
setTimeout(function () {
console.log('event fired: ', evt.type)
}, 1000)
})
})
}
规则说这样做:
function main (userName) {
var foo = ['bar', 'baz']
_.forEach(foo, createClosure_addEachListener(userName))
}
function createClosure_addEachListener (userName) {
return addEachListener
function addEachListener (item) {
console.info(userName + ' add the ' + item + 'event listener')
document.addEventListener(item, logEventIn1Second)
}
}
function logEventIn1Second (evt) {
var functionToCall = logEvent.bind(evt.type)
doItIn1Second(functionToCall)
}
function doItIn1Second (func) {
setTimeout(func, 1000)
}
function logEvent (type) {
console.log('event fired: ', type)
}
此示例故意过度。在这种简单的情况下,当然,这里不需要应用这个使代码更难阅读的规则。但是如果闭包更复杂或需要多行代码,则此规则可以显着减小函数定义的大小并简化代码的读取。而且,该技术具有非常显着的性能效果。实际上,在第一个示例(嵌套闭包)中,包含
setTimeout
调用的匿名函数和包含console.log
调用的匿名函数被定义为数组的长度,因为它们实际上是被定义到foo.forEach
循环回调中。另一方面,第二种情况(遵循'展平封闭'规则),没有使用任何封闭范围变量的闭包被转换为标准函数(或回调),没有关闭。而且,它们被定义一次。
所以规则说两件事:
createClosure_addEachListener
),并将所有需要的变量传递为包装函数的参数,用于重新创建闭包所需的最小范围。所以,在我的例子中,我调用了包装函数createClosure_addEachListener
。我用这种方式命名这个功能之王(createClosure_<closureName>
)。
但我搜索了它是否存在某个标准或仅仅是流行的惯例来命名这种关闭工厂。
有人知道这样的命名约定吗?