在 JavaScript 中定义局部函数:使用 var 还是不使用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16439949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 04:41:03  来源:igfitidea点击:

Define local function in JavaScript: use var or not?

javascriptfunctionclosuresdeclaration

提问by Pavel S.

When a local (inner) function is declared in JavaScript, there are two options:

在 JavaScript 中声明局部(内部)函数时,有两种选择:

Declaring with varkeyword, assigning to the variable:

var关键字声明,赋值给变量:

(function() {
    var innerFunction1 = function() { ... };
    innerFunction1();
}());

Declaring just with the functionkeyword, without assigning to variable:

仅使用function关键字声明,而不分配给变量:

(function() {
    function innerFunction2() { ... };
    innerFunction2();
}());

I can see one advantage of the second: the function can be declared below the code which calls it so it is easier to separate private functions from the code actually executed.

我可以看到第二种方法的一个优点:该函数可以在调用它的代码下方声明,因此更容易将私有函数与实际执行的代码分开。

Which of them is betterand why?

哪个更好为什么

采纳答案by Selvakumar Arumugam

Actually there are 3 ways to declare a function:

实际上有3种方法可以声明一个函数:

  1. Function declaration: A Function Declaration defines a named function variable without requiring variable assignment. Function Declarations occur as standalone constructs and cannot be nested within non-function blocks. ex: function innerFunction1 () { };

  2. Function expression:: A Function Expression defines a function as a part of a larger expression syntax (typically a variable assignment). Functions defined via Function Expressions can be named or anonymous:

    a. Using an anonymous function - var innerFunction1 = function() { };

    b. Using a named function - var innerFunction1 = function myInnerFunction () { };

  3. Function constructor: A Function Constructor defines a function dynamically using the Function( ) constructor. Note that the function body is passed to the function as a string argument. var innerFunction1 = new Function (arg1, arg2, ... argN, functionBody)

  1. 函数声明:函数声明定义了一个命名函数变量,而不需要变量赋值。函数声明作为独立结构出现,不能嵌套在非函数块中。前任:function innerFunction1 () { };

  2. 函数表达式::函数表达式将函数定义为更大表达式语法(通常是变量赋值)的一部分。通过函数表达式定义的函数可以命名或匿名:

    一个。使用匿名函数 -var innerFunction1 = function() { };

    湾 使用命名函数 -var innerFunction1 = function myInnerFunction () { };

  3. 函数构造函数:函数构造函数使用Function() 构造函数动态定义一个函数。请注意,函数体作为字符串参数传递给函数。 var innerFunction1 = new Function (arg1, arg2, ... argN, functionBody)

The third method is not recommended because passing the function body as a string may prevent some JS engine optimizations, and it is prone to errors.

第三种方法不推荐,因为将函数体作为字符串传递可能会阻碍一些JS引擎优化,并且容易出错。

The differences between function declaration and function expression are subtle and you should choose whichever method suits your requirements best.

函数声明和函数表达式之间的区别很微妙,您应该选择最适合您需求的方法。

I use function expression where I need

我在需要的地方使用函数表达式

  1. a singleton function, or
  2. to determine which function to use programmatically (using a named function expression).
  1. 单例函数,或
  2. 确定以编程方式使用哪个函数(使用命名函数表达式)。

Some differences between a function declaration and a function expression are:

函数声明和函数表达式之间的一些区别是:

  1. Function expressions allow you to assign different functions to the same variable at different points.
  2. A function defined by a function declaration can be used before the function declaration itself (or basically anywhere in the current scope), whereas a function defined by a function expression can only be used after the point it is defined.
  1. 函数表达式允许您在不同的点将不同的函数分配给同一个变量。
  2. 由函数声明定义的函数可以在函数声明本身之前(或基本上在当前范围内的任何地方)使用,而由函数表达式定义的函数只能在定义点之后使用。

Click here to read the detailed comparisonof Function Declaration vs Function Expression vs Function Constructor @MDN

点击这里阅读函数声明 vs 函数表达式 vs 函数构造函数的详细比较@MDN

Note:A function declaration can be easily turned into a function expression by assigning it to a var.

注意:通过将函数声明分配给 var,可以很容易地将函数声明转换为函数表达式。

function foo() {}
alert(foo); // alerted string contains function name "foo"
var bar = foo;
alert(bar); // alerted string still contains function name "foo"

More Reading:

更多阅读:

回答by Halcyon

The two notations are functionally equivalent.

这两种符号在功能上是等效的。

You can assume that:

你可以假设:

function a() {}
function b() {}

is interpreted as:

被解释为:

var a, b;
a = function a() {};
b = function b() {};

This is why you don't have to declare- (not define!) before-use. You can reassign functions after you've defined them, just like you would with a variable. Functions get hoisted just like variables, because they are variables(mind=blown? good!).

这就是为什么您不必在使用前声明(而不是定义!)。您可以在定义函数后重新分配它们,就像使用变量一样。函数就像变量一样被提升,因为它们是变量(头脑=爆炸?好!)。



Declare-before-use

使用前声明

function a() { b(); } // using b before it's declared?
function b() {}

becomes:

变成:

var a, b;
a = function a() { b(); }; // nope! b is declared, we're good
b = function b() {};


Redefining a function

重新定义一个函数

function a() { alert("a"); }
a = function b() { alert("b"); }; // that's weird!

becomes:

变成:

var a;
a = function a() { alert("a"); };
a = function b() { alert("b"); }; // oh, that looks normal


Declare vs define

声明与定义

Declare is: var x. In English: "I will be using variable x".

声明是:var x。英语:“我将使用变量x

Define is: x = 5. In English "Variable xnow has the value 5".

定义为:x = 5。在英语中“变量x现在具有值5

Declare-before-use is required and enforced in "use strict". Define-before-use is not required. If your variables are defined in run-time you're good.

"use strict". 不需要使用前定义。如果您的变量是在运行时定义的,那您就很好。

So var x = 5is botha declaration and a definition, as is function a() {}.

所以var x = 5两个声明和定义,为是function a() {}

Be cautious when naming functions not to override an existing variable:

命名函数时要小心,不要覆盖现有变量:

var a = function () { alert("a"); };
var b = function a() { alert("b"); };
a(); // prints "b"

Linttools will pick up on this.

Lint工具会注意到这一点。



When to use which notation?

什么时候使用哪种符号?

I would recommend using the function expression notation (var a = function () {}) only when you are reassigned the value of alater on. The function expression then signals to the reader that ais going to get reassigned and that it is intentional.

我建议var a = function () {}您仅在a稍后重新分配 的值时才使用函数表达式符号 ( ) 。然后,函数表达式向读取器发出信号,表明a将被重新分配并且这是有意的

Another (minor) argument for the function expression notation is a Lint tool like JSLint that might require you to declare (not define!) your functions before you use them. If you have functions with a recursive definition, ie. acalls band bcalls a, you can not declare one before the other by using the function declaration notation.

函数表达式符号的另一个(次要)参数是像 JSLint 这样的 Lint 工具,它可能需要您在使用函数之前声明(而不是定义!)您的函数。如果您有递归定义的函数,即。a调用bb调用a,您不能使用函数声明符号在另一个之前声明一个。

Edit notes:I've made a slight revision about named anonymous functions. It can be usefull to name anonymous functions when you're looking at a stacktrace. The named function will give more context lest it be logged as 'anonymous'.

编辑说明:我对命名匿名函数进行了轻微修改。在查看堆栈跟踪时命名匿名函数会很有用。命名函数将提供更多上下文,以免它被记录为“匿名”。

回答by MarmiK

The difference is that function with VARis defined at run-time,

不同之处在于函数 withVAR是在运行时定义的,

whereas function() without VAR is defined at parse-timefor a script block.

而没有 VAR 的 function() 是在解析时为脚本块定义的。

That is the only major difference..

这是唯一的主要区别..

So, user will decide on the requirement basis, which to use, and which suits the requirement..

因此,用户将根据需求决定使用哪个,以及哪个适合需求。

回答by Travis J

There is not any difference in output. Both can still be invoked and both can have their prototype accessed by name.

输出没有任何区别。两者仍然可以被调用,并且都可以通过名称访问它们的原型。

There are only two real differences.

只有两个真正的区别。

1) Readability and preference

1) 可读性和偏好

Some people find one way easier to read than others, and they will in turn base their convention on that style. Following convention is important.

有些人发现一种比其他人更容易阅读的方式,他们反过来会根据这种风格来制定他们的惯例。遵循惯例很重要。

2) Slightspace saver

2)稍微节省空间

With minification being ever more relevant for scripts, you can see how it might be advantageous to use the second approach as it does not require the use of varor =which will save a basically insignificant 4 characters of space in your minified script.

随着缩小与脚本越来越相关,您可以看到使用第二种方法可能是多么有利,因为它不需要使用var=将在您的缩小脚本中节省基本上无关紧要的 4 个字符的空间。



Executive Summary

执行摘要

It all comes down to preference. Which is better? You tell me. Personally, I will use varif I intend to make an object out of it with newand then I will capitalize the first letter, such as Person. Otherwise, I tend to camelCase it and omit the use of var.

这一切都归结为偏好。哪个更好?你告诉我。就个人而言,var如果我打算用它制作一个对象,我将使用new,然后我将大写第一个字母,例如 Person。否则,我倾向于使用驼峰命名并省略var.

回答by lib3d

  • varwithout function name

    • is better if you master your variable declarations: especially whenthey are declared.
  • var没有函数名

    • 如果您掌握变量声明会更好:尤其是声明它们



  • Function named without var:

    • implies a so named variable declaration at the beginning of the current scope and it may prevent from some errors,
    • but: declaring a function this way, using a closure variable declared with varwill fail if this function is called before the closure variable is even declared. So, you have to know what you do.
  • 没有命名的函数var

    • 在当前作用域的开头隐含一个如此命名的变量声明,它可以防止一些错误,
    • 但是:以这种方式声明函数,var如果在声明闭包变量之前调用此函数,则使用声明为 with 的闭包变量将失败。所以,你必须知道你在做什么。



  • Function named with or without var

    • is good for class declaration,
    • and for profiling cause, for instance, Chrome dev profiling tool will be more explicit if functions are not anonymous: they will have an explicit name and you will know where is the slow part of your code.
  • 有或没有命名的函数 var

    • 有利于类声明,
    • 例如,对于分析原因,如果函数不是匿名的,Chrome 开发分析工具将更加明确:它们将具有明确的名称,您将知道代码的缓慢部分在哪里。



  • Function named and with var

    • is the way to have the function as a named scope without having the declared variable as a closure
    • while keeping the mastering of variable declaration order.
  • 函数命名和 var

    • 是将函数作为命名范围而不将声明的变量作为闭包的方法
    • 同时保持对变量声明顺序的掌握。

回答by cavila

Local declarations should always use var.

局部声明应始终使用 var。

Well I would say that first is better since it is a local scope and memory could be cleared after symbol not more in use.

好吧,我会说第一个更好,因为它是一个本地范围,并且可以在符号不再使用后清除内存。

There is also a note on google javascript style guide saying that the second form is not part of standard so it should not be used.

还有一个关于 google javascript style guide 的注释说第二种形式不是标准的一部分,所以不应该使用它。

Function Declarations Within Blocks

Do not do this:

if (x) { function foo() {} } While most script engines support Function Declarations within blocks it is not part of ECMAScript (see ECMA-262, clause 13 and 14). Worse implementations are inconsistent with each other and with future EcmaScript proposals. ECMAScript only allows for Function Declarations in the root statement list of a script or function. Instead use a variable initialized with a Function Expression to define a function within a block:

if (x) {

var foo = function() {}

}

块内的函数声明

不要这样做:

if (x) { function foo() {} } 虽然大多数脚本引擎支持块内的函数声明,但它不是 ECMAScript 的一部分(参见 ECMA-262,第 13 和 14 条)。更糟糕的实现彼此不一致,并且与未来的 EcmaScript 提案不一致。ECMAScript 只允许在脚本或函数的根语句列表中使用函数声明。而是使用用函数表达式初始化的变量来定义块内的函数:

如果 (x) {

var foo = function() {}

}

Source http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml.

来源http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml

回答by Binu Pandian

Agree with @MarmiK. Also the difference between two methods is the scope.While function declaration assigns local scope by default, the scope of the function assigned to a variable depends on the scope of the variable.

同意@MarmiK。两种方法之间的区别也在于范围。虽然函数声明默认分配局部作用域,但分配给变量的函数作用域取决于变量的作用域。

var a;
(function() {
    var innerFunction1 = function() { ... };//local scope
    a=innerFunction1;//assigning to a global variable
}());

can be accessed globally. Go with the function declaration if you dont need to change the scope. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope

可以全局访问。如果您不需要更改范围,请使用函数声明。 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope

EDIT:

编辑:

var a;
(function() {
    function innerFunction1() { ... };//local scope
    a=innerFunction1;//It works too(Don't know why it should though)
}());

So, as pointed out by @Frits, there seems to be no scope advantage in using one type over the other.

因此,正如@Frits 所指出的,使用一种类型似乎没有范围优势。

回答by Adrien Be

Defining a javascript function

定义一个 javascript 函数

As mentioned by Vega, there are 3 ways of defining a function:

正如 Vega 所提到的,有 3 种定义函数的方法:

  1. function constructor
  2. function declaration
  3. function expression
  1. 函数构造器
  2. 函数声明
  3. 函数表达式


Cons of Function constructor:

函数构造函数的缺点:

Function constructors needs the function body as a string which:

函数构造器需要函数体作为字符串,它:

  • may prevent some JS engine optimizations
  • makes the syntax incredibly hard to write: need to escape special characters & some other madness, see below

    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.

  • 可能会阻止一些 JS 引擎优化
  • 使语法难以编写:需要转义特殊字符和其他一些疯狂,见下文

    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.

Cons of Function declaration:

函数声明的缺点:

It can be invoked before the function declaration itself, this actually introduces complexity:

它可以在函数声明本身之前调用,这实际上引入了复杂性:

Pros of Function expression:

函数表达式的优点:

Function expressions are simpler:

函数表达式更简单:

  • you "just know" what variable it is assigned to
  • you cannot invoke/reference the variable to which the function is assigned to before its definition, which is a consistent behavior with the rest of the javascript definitions
  • 你“只知道”它被分配给什么变量
  • 您不能在定义之前调用/引用函数分配给的变量,这是与其余 javascript 定义一致的行为


More about: Converting function declarations into function expressions

更多关于:将函数声明转换为函数表达式

Danger: As mentioned in "Cons of Function declaration" this can lead to many issues, below are more details about this.

危险:正如“函数声明的缺点”中提到的,这可能会导致许多问题,下面是有关此问题的更多详细信息。

It is very easy to convert function declarations into function expressions.

将函数声明转换为函数表达式非常容易。

"A function declaration ceases to be one when it either: becomes part of an expression is no longer a "source element" of a function or the script itself. A "source element" is a non-nested statement in the script or a function body"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Examples_2

“函数声明在以下情况下不再是一个:成为表达式的一部分不再是函数或脚本本身的“源元素”。“源元素”是脚本或函数中的非嵌套语句正文” https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Examples_2

"function statements are subject to hoisting. This means that regardless of where a function is placed, it is moved to the top of the scope in which it is defined. This relaxes the requirement that functions should be declared before used, which I think leads to sloppiness. It also prohibits the use of function statements in if statements. It turns out that most browsers allow function statements in if statements, but they vary in how that should be interpreted. That creates portability problems." - from the book: Javascript The Good Parts

“函数语句会被提升。这意味着无论函数被放置在哪里,它都会被移动到定义它的范围的顶部。这放宽了函数应该在使用前声明的要求,我认为这会导致到草率。它还禁止在 if 语句中使用函数语句。事实证明,大多数浏览器都允许在 if 语句中使用函数语句,但它们的解释方式各不相同。这会产生可移植性问题。” - 来自书中:Javascript The Good Parts



More about function expressions

有关函数表达式的更多信息

Syntax is such as:

语法如:

 var varName = function [name]([param] [, param] [..., param]) {    /* function expression */
      statements
 }

Things to note about [name](just after "function" in Syntax):

注意事项[name](就在语法中的“函数”之后):

  • The function name can be omitted, in which case the function becomes known as an anonymous function.
  • "A function name cannot be changed, while the variable the function is assigned to can be reassigned."
  • "The function name can be used only within the function's body." , you can use this feature to let the function call itself recursively.
  • 函数名可以省略,在这种情况下,函数被称为匿名函数
  • “函数名称不能更改,而函数分配给的变量可以重新分配。”
  • “函数名称只能在函数体内使用。” ,您可以使用此功能让函数递归调用自身。

Then using [name]you can do strange/funny things such as below. Note that I do not recommend doing this if you are new to function definitions.

然后使用[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

see live demo on jsbin.com/gijamepesu/1/edit?js,console

jsbin.com/gijamepesu/1/edit?js,console上查看现场演示

A typical implementation & usage would be such as below.

典型的实现和用法如下所示。

 var myCoolFunc = function ( username, firstName, lastName ) {    /* function expression */
      console.log('user ' + username + ' has the real full name ' + firstName + ' ' + lastName);
 }

 myCoolFunc();

Another thing to note: function expressions can be immediately invoked, vs function declarations cannot. This feature is used in IIFE, read more on What is the purpose of wrapping whole Javascript files in anonymous functions like “(function(){ … })()”?

还有一点要注意:函数表达式可以立即调用,而函数声明则不能。这个特性在 IIFE 中使用,阅读更多关于将整个 Javascript 文件包装在匿名函数中的目的是什么,比如“(function(){ … })()”?



Resources

资源

回答by cenk ebret

Zakas says that "As long as you always define functions before they used, you can feel free to use either function declarations or function expressions."

Zakas 说:“只要你总是在使用函数之前定义它们,你就可以随意使用函数声明或函数表达式。”

It means, if your code will be changed tomorrow by another person you dont know some day, and it is a big project that the developer cant find where the function is declared, you must use function declaration ( i mean function x(){} ), or if you declare the functions first anyway, you can use expressions.

意思是,如果你的代码明天被你不认识的人改了,而且是一个大项目,开发者找不到函数在哪里声明,你必须使用函数声明(我的意思是函数 x(){} ),或者如果您首先声明函数,则可以使用表达式。

回答by Oleg

I think that everybody who starts programming in JavaScript asks the question to themselves sooner or later. I would reformulate your question to:

我认为每个开始用 JavaScript 编程的人迟早都会问自己这个问题。我将您的问题重新表述为:

Should I use (prefer to use) function declaration(function statement) or function expression(varversion)?

我应该使用(更喜欢使用)函数声明函数语句)还是函数表达式var版本)?

In the most cases one can write good JavaScript code using only one from the constructions. It's clear that there are some important differences in semantic, but I want to stress, that in my opinion the answer on the question is mostly the answer about the style of the program. So I would answer that in the most real casesthe choice is the matter of the taste.

在大多数情况下,只使用结构中的一个就可以编写好的 JavaScript 代码。很明显,语义上存在一些重要差异,但我想强调的是,在我看来,这个问题的答案主要是关于程序风格的答案。所以我会回答,在最真实的情况下,选择是口味问题

The persons who prefer to use function statementuse it mostly not while they need define readonly function variable and not why they don't want to declare it before it will be used. In my opinion one uses it so mostly because one likesthe form.

喜欢使用函数语句的人大多不使用它,因为他们需要定义只读函数变量,而不是为什么他们不想在使用之前声明它。在我看来,使用它主要是因为人们喜欢这种形式。

So I think that there are no objectivelycorrect answer on your question. The choice is subjective. So I write in my answer which construction I personallyprefer and in which situations.

所以我认为你的问题没有客观正确的答案。选择是主观的。所以我在答案中写下我个人更喜欢哪种结构以及在哪种情况下。

My first languages were Pascal, C, Fortran, C++ etc. I used to use C# now. So when I started to write JavaScript programs I used at the beginning my existing styleof writing of programs from another languages. Later I changed the style of my JavaScript code corresponds to specific of the language.

我的第一门语言是 Pascal、C、Fortran、C++ 等。我现在使用 C#。所以当我开始编写 JavaScript 程序时,我一开始就使用了我现有的另一种语言编写程序的风格。后来我改变了我的 JavaScript 代码的风格,以适应特定语言。

I personallyprefer to use function expressionstyle and I declare all the functions in the first statement of the outer function. I find that the form mostly clear to JavaScript semantic where the name of the function is variablecontains a function value. The name of the function is subject to hoistinglike any other variable. For example my code look like below

个人更喜欢使用函数表达式风格,我在外部函数的第一条语句中声明所有函数。我发现这种形式对于 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);
}());

I use function statementvery seldom and only if I declare the constructor of the class like:

我很少使用函数语句,并且仅当我声明类的构造函数时,例如:

(function() {
    "use strict";
    function MyClass(x) {
        // the code of constructor
        this.abc = x;
    }
    var myInstance = new MyClass("xyz");
    alert(myInstance.abc);
}());

I try never use the third form:

我尽量不使用第三种形式:

(function() {
    "use strict";
    var myFunc1 = function myFunc2(x) {
            ...
        };
    ...    
}());

where myFunc2are declared additionally to myFunc1. The implementation of such form depends from web browser. It has sense probably in case of usage recursive functions.

wheremyFunc2额外声明到myFunc1. 这种形式的实现取决于网络浏览器。它可能在使用递归函数的情况下有意义。