105

这两种声明函数的方法有什么区别?

函数someFunc(){…}var someFunc=函数(){…}

我不是在技术层面上问。我并不是在问哪个更容易阅读,或者哪个风格更受欢迎。

0

8个答案8

重置为默认值
49

我和这里的大多数人意见不同。从技术上讲,这种语法可能对两种方式声明函数的含义相同(我的最后一句话不正确。我在一篇不同的帖子上读到了为什么他们在技术上存在差异,最后我会补充,为什么); 但它们在进化模式中发挥作用的方式是巨大的。我强烈推荐Doughlas Crockford的《Javascript:The Good Parts》。

但要用一种微妙而简单的方式证明我的观点;这是一个小例子。

//现有全球职能部门为每个人服务函数swearOutLoud(swearWord){alert(“You”+swearWord);}//全球职能部门的领土到此为止//这是海绵宝宝先生。他对自己的目标充满热情;但他有点粗鲁。var海绵机器人={name:“方裤”,swear:函数(swearWord){name=“海绵状”;alert(“You”+swearWord);返回此;}}//最后海绵宝宝也学会了礼貌。进化!spongeBob.apologize=函数(){警惕(“嘿”+“this.name”+“对不起,伙计!”);返回此;}//让海绵宝宝发誓,然后马上道歉(级联效应!!)alert(spongeBob.sear(“twit”).道歉());

如果你看看上面的代码,我声明了一个名为swearOutLoud的函数。这将从任何对象或调用中获取脏话,并向您提供输出。它可以使用传递给它的“this”参数和参数对任何对象进行操作。

然而,第二个声明声明为名为“spongeBob”的对象的属性。这一点值得注意;在这里,我正朝着对象驱动的行为前进。当我没有其他东西要返回时,我也会保持“级联效应”,返回“this”。

类似的操作在jquery中完成;如果您试图编写框架或其他东西,那么这种级联模式非常重要。您还将其链接到Builder设计模式。

但是,使用声明为对象属性的函数,我能够实现以对象为中心的行为,从而形成更好的编程范例。除非设计良好;使用全局访问在外部声明的单个函数导致了一种非面向对象的编码方式。不知何故,我更喜欢后者。

要想看到级联效应,请看最后一句话,你可以要求海绵宝宝立即发誓并道歉;尽管道歉后来被添加为属性。

我希望我能把我的观点说清楚。从技术角度来看,差异可能很小;但从设计和代码进化的角度来看,它是巨大的,并使世界变得不同。

但那只是我!要么接受,要么放弃

编辑:

因此,这两种调用在技术上是不同的;因为命名声明绑定到全局命名空间,并在解析时定义。甚至可以在声明函数之前调用。

//成功swearOutLoud(“该死”);函数swearOutLoud(swearWord){警报(“You”+swearWord)}

上述代码将正常工作。但下面的代码不会。

发誓(“该死!”);var swear=函数(swearWord){console.log(swearWord);}
2
  • 28
    这其中的主要部分尚不清楚,与问题无关。 评论 2009年12月18日9:37
  • 也许吧,但另一方面,海绵宝宝在和你说话
    – 莫兹戈
    评论 2017年11月24日15:40
14

使用的一个优点函数someFunc(){…}函数名出现在Firebug调试器中。以另一种方式声明的函数(var someFunc=函数(){…})作为匿名的.

5

实际上,不同之处在于,第二个声明使我们能够像这样声明函数,从而可以将函数作为对象的属性:

var myObject=新对象();myObject.someFunc=函数(){…};
5

从风格上看,第二个示例与其他常用的声明函数的方法更为一致,因此可以认为它更具可读性

this.someFunc=函数(){…}...someFunc:function(){…},

然而,如前所述,它是匿名的,因此在分析时不会显示名称。声明函数的另一种方法如下,可以两全其美

var someFunc=函数someFunc(){…}
0
2

另一个区别是,在大多数浏览器上,后者允许您根据情况定义不同的实现,而前者则不允许。如果您试图定义将EventListener添加到功能如下:

if(document.addEventListener){函数addEventListenerTo(目标、事件、侦听器){....}}else if(document.attachEvent){函数addEventListenerTo(目标、事件、侦听器){....}}其他{函数addEventListenerTo(目标、事件、侦听器){....}}

在某些浏览器上,所有函数最终都会被解析,最后一个函数优先。结果:上述方法不起作用。不过,将匿名函数分配给变量是可行的。您还可以应用函数和基本函数面向方面编程使用分配给变量的匿名函数的技术。

var fib=记忆(函数(n){如果(n<0),则返回0;如果(n<2),返回1;返回fib(n-1)+fib(n-2);});...//修补$library函数如果(…){$=大约($,fixArg,fixResult);}
2

第一种形式:

函数测试(){}

是一种公认的语法,第二种形式是:

var测试=函数(){…}

允许您控制函数的范围(通过使用var;如果没有var,它将是全局的)。

你甚至可以同时做到这两件事:

var测试=函数测试(){…test();…}

这允许您以第二种形式定义递归函数。

1
  • 1
    我不同意第一种形式是一种公认的语法,而第二种形式。它们只是不同的形式,顺便说一句,它们是常用的。此外,命名函数表达式(上一个示例中使用的)在IE中有奇怪的行为。请参阅以下文章:yura.thinkweb2.com/named-function-expressions公司 评论 2009年12月18日9:50
1

为了可读性,我认为第一个显然更好。未来的维护程序员,即使假设他们对javascript足够熟悉,知道这个线程中出现的许多细节,也会采用第一种格式。

例如,如果有一天他们想用ctrl-f搜索函数的定义,看看里面发生了什么,他们会首先搜索someFunc=函数()函数someFunc()?

此外,为了获得完全的排版效果(因为我们谈论的是可读性),读者通常会快速扫描文本,如果他们在寻找函数定义,他们更倾向于跳过以“var”开头的一行。

我知道这是一个非技术性的答案,但人类阅读代码比计算机更难。

1

当你写作时

函数Test(){}

JavaScript实际上是在创建一个属性,并将函数对象分配给该属性,一旦调用,该函数对象将执行函数定义中报告的代码。属性已附着到对象窗口,或指向包含函数定义的对象。

9
  • 1
    这里有一些误解:首先,JavaScript中的命名函数和匿名函数之间存在差异,可以通过调用toString(字符串)在函数上。其次,虽然函数声明确实会向当前变量对象添加属性,但这只是全局对象(又称为窗口在浏览器中)在全局代码中(例如与函数内部相反)。因此,你的第三段是完全错误的。(续…) 评论 2009年12月18日9:46
  • 1
    …第三,函数被赋给变量对象的时间不同。由函数声明创建的函数(例如。函数test(){})可以在出现在它之前的代码中使用,这对于由函数表达式声明的函数(例如。var测试=函数(){};) 评论 2009年12月18日9:46
  • 1
    这并不是《JavaScript:The definition Guide》中所报道的,该指南明确指出:“当JavaScript解析器遇到函数定义时,它会解析并存储(不执行)构成函数主体的内容。它定义了一个属性(如果函数定义与另一个函数嵌套,则在调用对象中;否则,在全局对象中)与保存函数的函数同名。 评论 2009年12月18日12:30
  • 我删除了不正确的部分。关键是在这两种情况下,JavaScript解释器都会创建一个属性;从技术上讲,按照OP的要求,没有任何差异。 评论 2009年12月18日12:35
  • 我不知道你不同意我的哪一点。它是哪一个?关于你现在的回答,我的第一点仍然有效。我的第二点似乎仍然成立,因为函数体中的函数声明不会成为全局对象的属性。我的第三点仍然有效,因为它指出了函数声明和函数表达式之间的区别,而您的答案并没有提到。 评论 2009年12月19日0:54

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.