[英]Define local function in JavaScript: use var or not?
在JavaScript中声明本地(内部)函数时,有两个选项:
使用var
关键字声明,分配给变量:
(function() {
var innerFunction1 = function() { ... };
innerFunction1();
}());
仅使用function
关键字声明,而不指定给变量:
(function() {
function innerFunction2() { ... };
innerFunction2();
}());
我可以看到第二个的一个优点:函数可以在调用它的代码下面声明,因此更容易将私有函数与实际执行的代码分开。
哪个更好 , 为什么 ?
实际上有三种方式来声明一个函数:
函数声明 :函数声明定义了一个命名函数变量,无需变量赋值。 函数声明作为独立构造出现,不能嵌套在非函数块中。 例如: function innerFunction1 () { };
函数表达式:: Function Expression将函数定义为更大的表达式语法(通常是变量赋值)的一部分。 通过函数表达式定义的函数可以命名或匿名:
一个。 使用匿名函数 - var innerFunction1 = function() { };
湾 使用命名函数 - var innerFunction1 = function myInnerFunction () { };
函数构造函数 :函数构造函数使用Function()构造函数动态定义函数。 请注意,函数体作为字符串参数传递给函数。 var innerFunction1 = new Function (arg1, arg2, ... argN, functionBody)
不建议使用第三种方法,因为将函数体作为字符串传递可能会阻止某些JS引擎优化,并且容易出错。
函数声明和函数表达式之间的区别是微妙的,您应该选择最适合您要求的方法。
我在需要的地方使用函数表达式
函数声明和函数表达式之间的一些区别是:
单击此处阅读函数声明与函数表达式与函数构造函数@MDN的详细比较
注意:通过将函数声明赋值给var,可以很容易地将函数声明转换为函数表达式。
function foo() {}
alert(foo); // alerted string contains function name "foo"
var bar = foo;
alert(bar); // alerted string still contains function name "foo"
更多阅读:
这两个符号在功能上是等价的。
你可以假设:
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
声明vs定义
声明是: 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"
何时使用哪种符号?
我会建议使用的函数表达式表示法( var a = function () {}
仅当您重新分配的值a
以后。 那么函数表达信号给读者a
是会得到重新分配,它是故意的 。
函数表达式表示法的另一个(次要)参数是像JSLint这样的Lint工具,它可能要求您在使用它们之前声明(不定义!)函数。 如果您有具有递归定义的函数,即。 a
调用b
和b
调用a
,你不能使用函数声明表示法先声明一个。
编辑笔记:我对命名的匿名函数做了一些修改。 当您查看堆栈跟踪时,命名匿名函数会很有用。 命名函数将提供更多上下文,以免将其记录为“匿名”。
区别在于VAR
函数是在运行时定义的,
而在没有VAR的function()是在脚本块的分析时定义的。
这是唯一的主要区别..
因此,用户将决定要求的基础,使用哪种,哪些适合要求。
输出没有任何差异。 两者仍然可以被调用,并且两者都可以通过名称访问它们的原型。
只有两个真正的差异。
1)可读性和偏好
有些人发现一种方法比其他人更容易阅读,他们反过来会根据这种风格建立会议。 遵循惯例很重要。
2) 轻微节省空间
随着缩小与脚本越来越相关,您可以看到使用第二种方法可能是有利的,因为它不需要使用var
或=
这将在您的缩小脚本中保存基本上无关紧要的4个字符的空间。
执行摘要
这一切都归结为偏好。 哪个更好? 你告诉我。 就个人而言,如果我打算用new
创建一个对象,我会使用var
然后我会将第一个字母大写,例如Person。 否则,我倾向于使用它并省略var
的使用。
var
没有函数名
名为without var
函数:
var
声明的闭包变量将失败。 所以,你必须知道你做了什么。 使用或不使用var
命名的函数
函数名为和var
本地声明应始终使用var。
好吧,我会说第一个更好,因为它是一个本地范围,内存可以在符号不再使用后清除。
谷歌javascript风格指南还有一个说明,说第二种形式不是标准的一部分,所以不应该使用它。
块内的函数声明
不要这样做:
if(x){function foo(){}}虽然大多数脚本引擎支持块内的函数声明,但它不是ECMAScript的一部分(参见ECMA-262,第13和14节)。 更糟糕的实现彼此不一致,并与未来的EcmaScript提议不一致。 ECMAScript仅允许在脚本或函数的根语句列表中使用函数声明。 而是使用使用函数表达式初始化的变量来定义块中的函数:
if(x){
var foo = function(){}
}
来源http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml 。
同意@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所指出的,使用一种类型而不是另一种类型似乎没有范围优势。
Zakas说:“只要你在使用之前总是定义函数,你就可以随意使用函数声明或函数表达式。”
这意味着,如果你的代码明天将由另一个你不知道的人改变,并且这是一个开发人员无法找到声明函数的大项目,你必须使用函数声明(我的意思是函数x(){} ),或者如果你首先声明函数,你可以使用表达式。
我认为每个开始用JavaScript编程的人迟早都会问自己这个问题。 我会将你的问题重新表述为:
我应该使用(更喜欢使用) 函数声明 ( 函数声明 )还是函数表达式 ( var版本)?
在大多数情况下,人们只能使用构造中的一个编写好的JavaScript代码。 很明显,语义上存在一些重要的差异,但我想强调的是,在我看来,问题的答案主要是关于程序风格的答案。 所以我会回答, 在最真实的情况下 ,选择是品味的问题 。
喜欢使用函数语句的人主要不是在他们需要定义只读函数变量时使用它而不是为什么他们不想在使用它之前声明它。 在我看来,人们之所以使用它,主要是因为喜欢这种形式。
所以我认为你的问题没有客观正确的答案。 选择是主观的 。 所以我在答案中写下我个人喜欢哪种结构以及在哪种情况下。
我的第一语言是Pascal,C,Fortran,C ++等。我过去常常使用C#。 因此,当我开始编写JavaScript程序时,我在开始时使用了另一种语言编写程序的现有风格 。 后来我改变了我的JavaScript代码的风格,对应于特定的语言。
我个人更喜欢使用函数表达式样式,并在外部函数的第一个语句中声明所有函数。 我发现JavaScript语义中的形式大多是清晰的,其中函数的名称是变量包含函数值。 函数的名称可以像任何其他变量一样提升 。 例如,我的代码如下所示
(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
之外另外声明的myFunc1
。 这种形式的实现取决于Web浏览器。 它可能在使用递归函数的情况下有意义。
正如Vega所提到的,有三种定义函数的方法:
函数构造函数需要函数体作为字符串:
使语法难以写:需要逃避特殊字符和其他一些疯狂,见下文
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.
它可以在函数声明本身之前调用,这实际上引入了复杂性:
函数表达式更简单:
危险:正如“功能声明的缺点”中所提到的,这可能导致许多问题,下面是关于此的更多细节。
将函数声明转换为函数表达式非常容易。
“当函数声明成为表达式的一部分不再是函数或脚本本身的”源元素“时,函数声明就不再是一个。”源元素“是脚本中的非嵌套语句或函数body“ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Examples_2
“函数语句需要提升。这意味着无论函数放在何处,它都会移动到定义它的作用域的顶部。这样就放松了在使用之前声明函数的要求,我认为它也禁止在if语句中使用函数语句。事实证明,大多数浏览器都允许在if语句中使用函数语句,但它们的解释方式各不相同。这就产生了可移植性问题。“ - 从书中: Javascript好的部分
语法如下:
var varName = function [name]([param] [, param] [..., param]) { /* function expression */
statements
}
关于[name]
注意事项(在语法中的“function”之后):
然后使用[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上的现场演示
典型的实现和使用将如下所示。
var myCoolFunc = function ( username, firstName, lastName ) { /* function expression */
console.log('user ' + username + ' has the real full name ' + firstName + ' ' + lastName);
}
myCoolFunc();
另外需要注意的是:函数表达式可以立即调用,而函数声明则不能。 这个功能在IIFE中使用,详细了解在“(function(){...})()”这样的匿名函数中包装整个Javascript文件的目的是什么?
简短的回答:在代码中没关系,但是你应该把var
放在一起以使它更具可读性。
长答案: JavaScript中的局部变量,就像JavaScript中的全局变量一样,可以使用或不使用var
定义。 因此,程序的功能不会受到var
缺乏或存在的干扰。 因为使用var
读取代码更容易,所以建议在首次声明变量时将var
放在变量之前。 但是如果你想要它是不可读的,那么你不应该在定义变量之前放置var
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.