下面是一个函数语句。它可以单独存在。
function foo(){ 
    alert("This is an alert"); 
}
它可以像这样“调用”(执行):
foo();
下面是一个函数表达式(如匿名函数**见底部编辑**)。与任何其他表达式一样,它就像一个右值,您可以将它分配给一个变量
var f = function (){ 
    alert("This is an alert"); 
};
然后,可以像这样“调用”(执行):
f();
或者您可以像这样使用运算符:
(function (){ 
 alert("This is an alert"); 
})();
请注意,这个变量现在可以作为参数传递给其他函数!(即我们可以将函数作为参数传递)。
现在,让我们分析一下:
(function( window, undefined ) {
    //blah blah blah -1
    //blah blah blah -2
})(window);
这可以分为两个:
var f = function( window, undefined ) {
    //blah blah blah
};
f(window);
该函数(分配给 f)有 2 个参数,window并且undefined. 我们将第一个参数作为window(由浏览器提供给调用者;它是一个全局对象)传递。请注意,我们没有传递任何第二个参数。但是由于我们期望函数中有第二个参数但没有传递任何参数,Javascript 解释器将为它分配一个undefined值(如解释器中定义的那样)。所以变量(参数)undefined现在包含未定义。
接受这两个值作为参数的主要目的是使函数独立于全局变量。(想象一下,如果某些 JS 脚本或浏览器插件将 undefined 更改为其他内容会发生什么!)
参考:
 https ://developer.mozilla.org/en-US/docs/JavaScript/Guide/Functions 
https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Expressions_and_Operators
编辑:
正如@FelixKling 评论的那样,函数表达式不必是匿名的,它们可以有名称。
var f = function foo(){ 
    alert("This is an alert"); 
}
这是一篇关于它们用法的有趣文章。