在JavaScript中声明本地(内部)函数时,有两个选项:
使用var
关键字声明,分配给变量:
(function() {
var innerFunction1 = function() { ... };
innerFunction1();
}());
仅使用function
关键字声明,而不指定给变量:
(function() {
function innerFunction2() { ... };
innerFunction2();
}());
我可以看到第二个的一个优点:函数可以在调用它的代码下面声明,因此更容易将私有函数与实际执行的代码分开。
其中哪些更好且为什么?
答案 0 :(得分:44)
实际上有3种声明函数的方法:
Function declaration:函数声明定义了一个命名函数变量,无需变量赋值。函数声明作为独立构造出现,不能嵌套在非函数块中。例如:function innerFunction1 () { };
Function expression::函数表达式将函数定义为更大表达式语法(通常是变量赋值)的一部分。通过函数表达式定义的函数可以命名或匿名:
一个。使用匿名函数 - var innerFunction1 = function() { };
湾使用命名函数 - var innerFunction1 = function myInnerFunction () { };
Function constructor:函数构造函数使用Function()构造函数动态定义函数。请注意,函数体作为字符串参数传递给函数。 var innerFunction1 = new Function (arg1, arg2, ... argN, functionBody)
不建议使用第三种方法,因为将函数体作为字符串传递可能会阻止某些JS引擎优化,并且容易出错。
函数声明和函数表达式之间的差异是微妙的,您应该选择最适合您需求的方法。
我在需要的地方使用函数表达式
函数声明和函数表达式之间的一些区别是:
注意:通过将函数声明赋值给var,可以很容易地将函数声明转换为函数表达式。
function foo() {}
alert(foo); // alerted string contains function name "foo"
var bar = foo;
alert(bar); // alerted string still contains function name "foo"
更多阅读:
答案 1 :(得分:7)
这两个符号在功能上是等价的。
您可以认为:
function a() {}
function b() {}
被解释为:
var a, b;
a = function a() {};
b = function b() {};
这就是为什么你不必在使用之前声明 - (不定义!)。您可以在定义函数后重新分配函数,就像使用变量一样。函数就像变量一样被提升,因为它们是变量(mind = blown?good!)。
<强>声明-前使用强>
function a() { b(); } // using b before it's declared?
function b() {}
变为:
var a, b;
a = function a() { b(); }; // nope! b is declared, we're good
b = function b() {};
重新定义功能
function a() { alert("a"); }
a = function b() { alert("b"); }; // that's weird!
变为:
var a;
a = function a() { alert("a"); };
a = function b() { alert("b"); }; // oh, that looks normal
声明与定义
声明是:var x
。用英语:“我将使用变量x
”。
定义是:x = 5
。在英语中“变量x
现在具有值5
”。
需要在使用前声明并在"use strict"
中强制执行。不需要在使用前定义。如果你的变量是在运行时定义的那么你就是好的。
所以var x = 5
都是声明和定义,function a() {}
也是如此。
在命名函数时不要覆盖现有变量时要小心:
var a = function () { alert("a"); };
var b = function a() { alert("b"); };
a(); // prints "b"
Lint工具会对此有所了解。
何时使用哪种表示法?
我建议仅在稍后重新分配var a = function () {}
的值时才使用函数表达式表示法(a
)。函数表达式然后向读者发出信号,a
将重新分配并且它是故意的。
函数表达式表示法的另一个(次要)参数是像JSLint这样的Lint工具,可能需要您在使用它们之前声明(不定义!)函数。如果您有具有递归定义的函数,即。 a
调用b
和b
调用a
,您不能使用函数声明表示法先声明一个。
编辑备注:我对命名的匿名函数做了一些修改。当您查看堆栈跟踪时,命名匿名函数会很有用。命名函数将提供更多上下文,以免将其记录为“匿名”。
答案 2 :(得分:4)
区别在于VAR
的功能是在运行时定义的,
而没有VAR的function()在脚本块的分析时间定义。
这是唯一的主要区别..
因此,用户将决定要求的基础,使用哪种,哪种适合要求..
答案 3 :(得分:2)
输出没有任何差异。两者仍然可以被调用,并且两者都可以通过名称访问它们的原型。
只有两个真正的区别。
1)可读性和偏好
有些人发现一种方式比其他人更容易阅读,他们反过来会根据这种方式制定约会。遵循惯例很重要。
2)轻微节省空间
随着缩小与脚本越来越相关,你可以看到使用第二种方法可能是有利的,因为它不需要使用var
或=
这将节省一个基本上无关紧要的缩小的脚本中有4个字符的空格。
执行摘要
这一切都取决于偏好。哪个更好?你告诉我。就个人而言,如果我打算用var
创建一个对象,我会使用new
,然后我会将第一个字母大写,例如Person。否则,我倾向于使用它,并省略var
的使用。
答案 4 :(得分:1)
var
没有功能名称
以var
命名的函数:
var
声明的闭包变量将失败。所以,你必须知道你做了什么。
使用或不使用var
以var
答案 5 :(得分:1)
本地声明应始终使用var。
我会说第一个更好,因为它是一个本地范围,并且在符号不再使用后可以清除内存。
谷歌javascript风格指南中还有一条说明,第二种形式不属于标准,因此不应使用。
块内的功能声明
不要这样做:
if(x){function foo(){}}虽然大多数脚本引擎都支持 块内的函数声明它不是ECMAScript的一部分(参见 ECMA-262,第13和14条)。更糟糕的实现是不一致的 相互之间以及未来的EcmaScript提案。仅限ECMAScript 允许函数声明在a的根语句列表中 脚本或功能。而是使用用Function初始化的变量 用于定义块内函数的表达式:
if(x){
var foo = function(){}
}
来源http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml。
答案 6 :(得分:1)
同意@MarmiK。 两种方法之间的区别也在于范围。虽然函数声明默认分配局部范围,但赋值给变量的函数范围取决于变量的范围。
var a;
(function() {
var innerFunction1 = function() { ... };//local scope
a=innerFunction1;//assigning to a global variable
}());
可以全局访问。 如果您不需要更改范围,请使用函数声明。 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope
var a;
(function() {
function innerFunction1() { ... };//local scope
a=innerFunction1;//It works too(Don't know why it should though)
}());
因此,正如@Frits所指出的那样,使用一种类型而不是另一种类型似乎没有范围优势。
答案 7 :(得分:0)
Zakas说“只要你在使用之前总是定义函数,你可以随意使用函数声明或函数表达式。”
这意味着,如果你的代码明天将由另一个你不知道的人改变,并且这是一个开发人员无法找到声明函数的大项目,你必须使用函数声明(我的意思是函数x( ){}),或者如果你首先声明函数,你可以使用表达式。
答案 8 :(得分:0)
我认为每个开始用JavaScript编程的人迟早都会问自己这个问题。我会将你的问题重新表述为:
我应该使用(更喜欢使用)函数声明(函数语句)还是函数表达式( var 版本)?
在大多数情况下,人们只能使用构造中的一个来编写好的JavaScript代码。很明显,语义上存在一些重要的差异,但我想强调的是,在我看来,问题的答案主要是关于程序风格的答案。所以我会在最实际的案例中回答 选择品味。
喜欢使用函数语句的人主要不是在他们需要定义readonly函数变量时使用它而不是为什么他们不想在使用它之前声明它。在我看来,人们使用它主要是因为一个喜欢形式。
所以我认为你的问题没有客观正确答案。选择是主观。所以我在回答中写出了我个人喜欢的构造以及在哪种情况下。
我的第一语言是Pascal,C,Fortran,C ++等。我过去常常使用C#。因此,当我开始编写JavaScript程序时,我开始使用其他语言编写程序的现有样式。后来我改变了我的JavaScript代码的风格,对应于特定的语言。
我个人更喜欢使用函数表达式样式,并在外部函数的第一个语句中声明所有函数。我发现JavaScript语义中的形式大多是清晰的,其中函数的名称是 variable 包含一个函数值。与任何其他变量一样,函数的名称受hoisting的约束。例如,我的代码如下所示
(function() {
"use strict";
var myFunc1 = function (x) {
// body where I can use x and this
alert("x=" + x + ", this.foo=" + this.foo);
},
localVar1 = {foo: "bar"};
myFunc1.call(localVar1, 1);
}());
我很少使用函数语句,只有当我声明类的构造函数时才会这样:
(function() {
"use strict";
function MyClass(x) {
// the code of constructor
this.abc = x;
}
var myInstance = new MyClass("xyz");
alert(myInstance.abc);
}());
我尝试永远不要使用第三种形式:
(function() {
"use strict";
var myFunc1 = function myFunc2(x) {
...
};
...
}());
其中myFunc2
另外声明为myFunc1
。这种形式的实现取决于Web浏览器。它可能在使用递归函数的情况下有意义。
答案 9 :(得分:0)
正如Vega所提到的,有三种定义函数的方法:
函数构造函数需要函数体作为字符串:
使语法难以理解:需要转义特殊字符&amp;其他一些疯狂,见下文
var foo = (new Function("var bar = \'FOO!\';\nreturn(function() {\n\talert(bar);\n});"))();
foo(); // The segment "function() {\n\talert(bar);\n}" of the function body string is not re-parsed.
它可以在函数声明本身之前调用,这实际上引入了复杂性:
函数表达式更简单:
危险:如&#34;功能声明的缺点&#34;这可能会导致许多问题,下面是更多有关此问题的详细信息。
将函数声明转换为函数表达式非常容易。
&#34;当一个函数声明成为表达式的一部分不再是一个&#34;源元素&#34;时,函数声明就不再是一个。函数或脚本本身。 A&#34;源元素&#34;是脚本中的非嵌套语句或函数体&#34; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Examples_2
&#34;函数语句需要提升。这意味着无论函数放在何处,它都会移动到定义函数的作用域的顶部。这放宽了在使用之前应该声明功能的要求,我认为这会导致邋iness。它还禁止在if语句中使用函数语句。事实证明,大多数浏览器都允许if语句中的函数语句,但它们的解释方式各不相同。这就产生了可移植性问题。&#34; - 来自书:Javascript The Good Parts
语法如下:
var varName = function [name]([param] [, param] [..., param]) { /* function expression */
statements
}
关于[name]
的注意事项(在&#34;函数&#34;语法之后):
然后使用[name]
你可以做下面的奇怪/有趣的事情。 请注意,如果您不熟悉函数定义,我建议不要这样做。
var count = 0;
var varName = function funcName() { /* function expression */
console.log('count is: ' + count );
if(count<1){
count++;
funcName(); /* calls function funcName another time */
}
};
varName(); // invokes function funcName via variable varName
funcName(); // throws an error as funcName is not reachable
查看jsbin.com/gijamepesu/1/edit?js,console
上的实时演示典型的实施&amp;用法如下所示。
var myCoolFunc = function ( username, firstName, lastName ) { /* function expression */
console.log('user ' + username + ' has the real full name ' + firstName + ' ' + lastName);
}
myCoolFunc();
另外需要注意的是:函数表达式可以立即调用,而函数声明则不能。此功能在IIFE中使用,请参阅What is the purpose of wrapping whole Javascript files in anonymous functions like “(function(){ … })()”?
答案 10 :(得分:-3)
简短回答:代码无关紧要,但您应该var
使其更具可读性。
长答案: JavaScript中的局部变量,就像JavaScript中的全局变量一样,可以使用或不使用var
进行定义。因此,程序的功能不会受到单词var
的缺失或存在的干扰。因为使用var
读取代码更容易,所以建议您在首次声明变量时将var
置于变量之前。但是如果你希望它不可读那么你就不应该在定义变量之前放置var
。