可能重复:
JavaScript: var functionName = function() {} vs function functionName() {}
在Javascript中提取函数有两种可能的方法:
var foo = function() { ... }
这有点做作;另一个常见的模式是:
var foo = {
baz: 43,
doSomething: function() {
// ...
}
}
与
function foo() {
// ...
}
是否有明确的理由偏好其中一个?
答案 0 :(得分:73)
这一切都取决于您声明功能的地方;吊装。
函数声明和变量声明总是被JavaScript解释器无形地移动到其包含范围的顶部("悬挂")。显然,功能参数和语言定义的名称已经存在。这意味着代码如下:
function foo() {
bar();
var x = 1;
}
实际上是这样解释的:
function foo() {
var x;
bar();
x = 1;
}
请注意,声明的分配部分未被提升。只有名字被悬挂。函数声明不是这种情况,整个函数体也将被提升。
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
在这种情况下,只有函数声明将其主体提升到顶部。名字' foo'被吊起,但尸体被遗忘,在执行期间被分配。
您可以为函数表达式中定义的函数指定名称,其语法类似于函数声明。这不会使它成为一个函数声明,并且名称不会被带入范围,也不会被提升。
foo(); // TypeError "foo is not a function"
bar(); // valid
baz(); // TypeError "baz is not a function"
bin(); // ReferenceError "bin is not defined"
var foo = function () {}; // anonymous function expression ('foo' gets hoisted)
function bar() {}; // function declaration ('bar' and the function body get hoisted)
var baz = function bin() {}; // named function expression (only 'baz' gets hoisted)
foo(); // valid
bar(); // valid
baz(); // valid
bin(); // ReferenceError "bin is not defined"
因此,如果您希望将功能提升到顶部,请使用function declaration
,否则请使用expression
。我更喜欢后者,因为我通常使用function expressions
方法构建对象文字。
当抛出错误时,命名function expressions
可以很方便。控制台将告诉您该功能是什么,而不是声明anonymous
又名堆栈跟踪。
答案 1 :(得分:10)
你在这里遇到了几件不同的事情,但我会先尝试解决你的主要问题。
一般......
function() { ... }
是函数表达式。语法上,这与2
或[4,5]
处于同一级别。这表示值。因此,var foo=function(){ ... }
每次都会按计划运作。
function foo() { ... }
是一个函数声明。这似乎和var foo=function(){...}
的做法相同,但有一点需要注意。作为一个声明,它的工作方式类似于JS中的变量提升概念(基本上,所有变量声明都是在评估任何表达式之前完成的。)
一个很好的例子来自here:
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
基本上可变的提升使得价值达到顶峰,所以这段代码相当于(理论上 ):
function test() {
var foo;//foo hoisted to top
var bar=function(){//this as well
alert("this will run!");
}
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
}
注意:我想利用这一点来说JS解释器很难遵循理论,所以不建议相信他们有些不确定的行为。 Here你会在理论和实践最终不起作用的部分末尾找到一个很好的例子(关于表达式与声明的主题还有更多细节)。
有趣的事实:在括号中包装function foo() {...}
会将其从声明转换为表达式,这可能会导致一些奇怪的代码,如
(function foo() { return 1; })();// 1
foo; //ReferenceError: foo is not defined
如果您没有理由,请不要这样做。
摘要 var foo=function(){ ... }
* sorta有点*与函数foo(){ ... }
相同,不同之处在于前者执行您认为应该执行的操作,而后者确实很奇怪除非你将它包装在parens中,否则会影响范围,JS解释器允许你在规范中做一些被认为是语法错误的事情,这样你就会认为错误的事情实际上是正确的等等......
请使用函数表达式(var f=function(){...}
)。没有真正的理由不这样做,特别是考虑到你在使用点语法时有点被迫这样做。
关于你触及的第二件事.....
我不确定该说些什么,它与其他一切完全不同。
var foo = {
baz: 43,
doSomething:function() {
...
}
}
这称为对象文字语法。基于此语法的JSON是a pretty neat way of formatting data,JS中的这种语法通常用于声明新对象,例如使用单例对象(避免声明函数和使用new的所有混乱)。它也可以像使用XML一样使用,并且是所有酷孩子都喜欢的......
无论如何,基本上对象文字语法的工作原理如下:
{ name1: val1, .... namek:valk }
此表达式是在其上初始化某些值的对象。所以做var obj={ name1: val1, .... namek:valk }
意味着:
obj.name1==val1;
obj['name1']==val1;// x['y'] is the same thing as x.y
...
obj.namek==valk;
那么这与我们的例子有什么关系呢?基本上,您的表达式通常用于声明单例对象。但是它也可以用来声明一个对象原型,所以有人以后可以做var newObj = Object.create(foo),newObj会把foo作为原型。
如果你想真正了解它的实用性,请详细研究原型继承。道格拉斯·克罗克福德在他的许多会谈的one中详细谈到了这一点。
答案 2 :(得分:2)
命名函数没什么好处
functionInstance.name
会显示您的姓名。 命名函数表达式
有一个缺点除了较少的风格控制之外,函数声明没有缺点
答案 3 :(得分:1)
您的问题实际上由两部分组成,因为如果将函数分配给变量或属性,则不一定要使函数匿名。
命名与匿名?
@Raynos清楚地突出了要点。关于命名函数的最好的部分是它们将在堆栈跟踪中显示自己。即使在将函数分配给变量/属性的情况下,最好为函数命名以帮助调试,但我不会说匿名函数是邪恶的。它们确实有很好的用途:
Are anonymous functions a bad practice in JavaScript?
函数声明与函数表达式?
对于问题的这一部分,我会向您推荐这个问题,因为它可能比我更深入地涵盖了这个主题
var functionName = function() {} vs function functionName() {}