函数表达在声明正确之前不能使用?但也传递了一个按键功能。这个魔法是怎么发生的?
我正在做一个代码并在我查看它时注意到它。
var controller = (function(budgetCtrl, UICtrl){
var setUpEventListeners = function(){
//CTRLADDITEM is called below
document.querySelector(DOM.inputBtn).addEventListener('click', **ctrlAddItem**);
document.addEventListener('keypress', function(e){
if(event.keyCode === 13 || event.which === 13){
**ctrlAddItem();**
}
});
}
var **ctrlAddItem** = function(){
updateBudget();
}
};
}
})(budgetController, UIController );
答案 0 :(得分:1)
这称为IIFE (Immediately Invoked Function Expression),它在Javascript以及Go等其他语言中相当常见。这是一个简单的版本......
(function() {
alert('invoked immediately');
})();
此代码将立即运行。注意:在定义之前调用不。它由尾部括号调用,在定义之后直接。这与完成同样的事情......
function doSomething() {
}
doSomething();
我们刚刚将该函数包装在括号中,然后将其称为()
,而不是按名称调用它。
如果将结果分配给变量,它会按预期工作,您将分配函数的结果。
// these two are equivalent
var result = (function () {
return 5;
})();
var result = 5;
现在,result
中的值将等于5
。
我们为什么要使用它们?
最常见的是,我们使用它们来隔离代码的范围,以防止它污染全局范围。例如,如果这是您的应用程序代码......
function MyApp() {
}
您现在通过创建window.MyApp
污染了全局范围。如果您使用的第三方库也提供了名为MyApp
的全局范围的函数,它将覆盖您的。为了防止这种情况,我们可以做...
(function(window) {
function MyApp() {}
MyApp();
})(window);
现在,MyApp
未附加到窗口,我们仍然可以访问该窗口。
进一步沿着兔子洞
您必须先将函数从声明转换为表达式,然后才能立即调用它。为此,请将其包装在括号中。
不工作
function (){
// do something
}()
DOES 工作(由于括号)
(function () {
})()
您也可以使用任何一元运算符代替括号。 所有这些工作
~function () {
}()
+function () {
}()
-function () {
}()
void function () {
}()
答案 1 :(得分:0)
你拥有的是:
// Pass ctrlAddItem
document.querySelector(DOM.inputBtn).addEventListener('click', ctrlAddItem);
// Include closure to ctrlAddItem in function expression
document.addEventListener('keypress', function(e){
if(event.keyCode === 13 || event.which === 13){
ctrlAddItem();
}
});
// later...
var ctrlAddItem = function(){ /* whatever */ }
因此声明了 ctrlAddItem ,因此在执行任何代码之前存在值 undefined 。在 addEventListener 中使用它时,它的值仍未定义。
但是,在外部函数完成之前(以及调用侦听器之前), ctrlAddItem 会被赋值。因此,当调用侦听器时,它是(对a)函数的引用。