在JavaScript中首选命名函数或匿名函数?
可能重复:
JavaScript:var functionName = function(){} vs function functionName(){}
有两种可能的方法在Javascript中提取函数:
var foo = function() { ... }
(这是有点人为的;另一种常见的模式是:
var foo = { baz: 43, doSomething:function() { ... } }
)
与
function foo() { ... }
有一个明确的理由喜欢一个或另一个?
这一切都归结于你声明你的职能的地方。 吊装。
函数声明和variables声明总是被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”这个名字被吊起来了,但遗体被遗忘了,在执行过程中被分配。
您可以给函数expression式中定义的函数赋予名称,语法就像函数声明一样。 这不是一个函数声明,这个名字不在范围之内,也没有被挂起。
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的顶部使用function declaration
否则使用expression
。 我更喜欢后者,因为我通常使用方法作为function expressions
构build对象文字。
命名的function expressions
在抛出错误时可以很方便。 控制台会告诉你该函数是什么,而不是陈述anonymous
又名堆栈跟踪 。
你在这里遇到了一些不同的事情,但是我会先尝试打你的主要问题。
一般来说….
function() { ... }
是一个函数expression式 。 在语法上,这与2
或[4,5]
级别相同。 这代表了一个价值 。 所以做var foo=function(){ ... }
将按照计划进行工作。
function foo() { ... }
是一个函数声明。 这可能看起来像var foo=function(){...}
,但是有个小警告。 作为一个声明,它类似于JS中variables提升的概念(基本上,所有variables声明都是在任何expression式被评估之前完成的)。
一个很好的例子是从这里 :
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解释者很难遵循理论,因此不build议对他们的某些行为有信任。 在这里,你会发现一个很好的例子,在理论和实践最终不起作用的部分结尾(还有一些关于expression式和声明的更多细节)。
有趣的事实:在括号中包装function foo() {...}
将其从一个声明转换为一个expression式,这可能导致一些奇怪的代码
(function foo() { return 1; })();// 1 foo; //ReferenceError: foo is not defined
如果您没有理由请不要这样做。
总结 var foo=function(){ ... }
是一个类似于函数foo(){ ... }
函数,除了前者在你认为应该做的事情上做了什么,而后者却是奇怪的东西除非你把它包装在parens里面,但是弄乱了范围,JS解释器允许你做规范中被认为是语法错误的东西,这样你就可以相信错误的东西实际上是正确的,等等。
请使用函数expression式 ( var f=function(){...}
)。 没有什么真正的理由不要这样做,特别是考虑到当你使用点语法的时候你有点被迫这样做。
关于第二件事,你碰到…..
我真的不知道该说些什么,这与其他一切完全不同。
var foo = { baz: 43, doSomething:function() { ... } }
这被称为对象文字语法。 基于这种语法的JSON是格式化数据的一种非常简洁的方式, JS中的这种语法经常被用来声明新的对象,比如单例对象(避免了声明一个函数和使用新的一切) 。 它也可以像使用XML一样使用,并且是所有酷的孩子们的首选。
无论如何,基本上对象文字的语法是这样的:
{ name1: val1, .... namek:valk }
这个expression式是一个具有初始化值的对象。 所以做var obj={ name1: val1, .... namek:valk }
意味着:
obj.name1==val1; obj['name1']==val1;// x['y'] is the same thing as xy ... obj.namek==valk;
那么这与我们的例子有什么关系呢? 基本上你的expression式经常被用来声明单例对象。 但是它也可以用来声明一个对象的原型,所以稍后有人可以做var newObj = Object.create(foo),newObj将foo作为原型。
仔细研究原型inheritance,如果你想真正得到它是多么有用。 道格拉斯·克罗克福德(Douglas Crockford)在他的一次谈话中详细谈到了这一点)。
命名function没有什么优势
- 名称为元分析。
functionInstance.name
会显示你的名字。 - 更重要的是,这个名字将被打印在堆栈中。
- 名字也有助于编写自我logging或识字代码。
命名函数expression式有一个缺点
- IE有NFE的内存泄漏
除了较less的文体控制之外,函数声明没有缺点
你的问题实际上由两部分组成,因为如果你的函数被分配给一个variables或者属性,你不一定非要匿名。
命名vs匿名?
@Raynos清楚地突出了要点。 关于命名函数的最好的部分是它们将显示在堆栈跟踪中。 即使在函数被分配给variables/属性的情况下,给你的函数起一个名字只是为了帮助debugging,但是我不会说匿名函数是邪恶的。 他们确实有一个很好的目的:
匿名函数在JavaScript中是不好的做法吗?
函数声明与函数expression式?
对于问题的这一部分,我会向你提出这个问题,因为它可能比我能深入的讨论更多的话题
var functionName = function(){} vs function functionName(){}