Javascript 这个函数表达式是如何工作的?

Javascript 这个函数表达式是如何工作的?,javascript,hoisting,Javascript,Hoisting,在声明正确之前不能使用Function express?但也传递给按键功能。这魔法是怎么发生的 我正在编写代码,在查看时注意到了它 var controller = (function(budgetCtrl, UICtrl){ var setUpEventListeners = function(){ //CTRLADDITEM is called below document.querySelector(DOM.inpu

在声明正确之前不能使用Function express?但也传递给按键功能。这魔法是怎么发生的

我正在编写代码,在查看时注意到了它

    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 );
这被称为,它在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
}()
~function () {

}()

+function () {

}()

-function () {

}()

void function () {

}()
确实有效(由于括号)

也可以使用任何一元运算符代替括号所有这些工作

function (){
   // do something
}()
~function () {

}()

+function () {

}()

-function () {

}()

void function () {

}()
你所拥有的是:

// 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的引用)函数。

easy===looooong
?请将代码减少到演示问题所需的最小值。很难判断“此函数”是什么。当您实际触发事件处理程序时,它将被声明。查找IIFE(立即调用的函数表达式)。代码太多,即使删除了几十行无用的空行。我想我明白你的意思了。我在代码笔中做了一个测试,所以基本上IIFE调用了所有的代码,带有尾随()-所以当安装事件监听器执行时,IIFE中的所有代码都已经发生了-正确吗?:是的,正确。所有这些代码都会立即运行。在javascript控制台中复制并粘贴我的第一个示例,警报将立即触发。您已经在一条语句中声明并调用了该函数。感谢您的帮助。我做了一些测试,虽然我知道IFFE是什么,但它似乎不起作用,为什么@Charlie Martin:(function(){document.getElementById('btn').addEventListener('click',Martin);var Martin=function(){alert('called instally')};}();没关系,我做了一些测试,发现了。调用a.init()时整个函数都已运行感谢您的帮助在Charlie Martin执行了一些测试--var a=(function(){function setUp(){document.getElementById('btn')。addEventListener('click',Martin);}var Martin=function(){alert('called instally')};return{init:function(){setUp(){setUp();}}; a、 init();您的第一个示例有一个小问题,那就是您在将函数
martin
传递给
addEventListener
之后定义了它,因此您确实传递了它
undefined
。这是javascript中的一个问题,这是另一个蠕虫的例子:)试试这个:
// these two are equivalent
var result = (function () {
    return 5;
})();

var result = 5;