繁体   English   中英

在JavaScript中定义本地函数:使用var还是不使用var?

[英]Define local function in JavaScript: use var or not?

在JavaScript中声明本地(内部)函数时,有两个选项:

使用var关键字声明,分配给变量:

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

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

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

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

哪个更好为什么

实际上有三种方式来声明一个函数:

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

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

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

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

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

不建议使用第三种方法,因为将函数体作为字符串传递可能会阻止某些JS引擎优化,并且容易出错。

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

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

  1. 单身功能 ,或
  2. 确定以编程方式使用哪个函数(使用命名函数表达式)。

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

  1. 函数表达式允许您在不同的点为同一个变量分配不同的函数。
  2. 函数声明定义的函数可以在函数声明本身之前使用(或者基本上在当前作用域中的任何位置),而函数表达式定义的函数只能在定义它之后使用。

单击此处阅读函数声明与函数表达式与函数构造函数@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"

Lint工具将会对此有所了解。


何时使用哪种符号?

我会建议使用的函数表达式表示法( var a = function () {}仅当您重新分配的值a以后。 那么函数表达信号给读者a是会得到重新分配,它是故意的

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

编辑笔记:我对命名的匿名函数做了一些修改。 当您查看堆栈跟踪时,命名匿名函数会很有用。 命名函数将提供更多上下文,以免将其记录为“匿名”。

区别在于VAR函数是在运行时定义的,

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

这是唯一的主要区别..

因此,用户将决定要求的基础,使用哪种,哪些适合要求。

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

只有两个真正的差异。

1)可读性和偏好

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

2) 轻微节省空间

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


执行摘要

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

  • var没有函数名

    • 如果掌握变量声明会更好:特别是声明它们


  • 名为without var函数:

    • 意味着在当前范围的开头有一个如此命名的变量声明,它可以防止出现一些错误,
    • 但是 :以这种方式声明一个函数,如果在声明闭包变量之前调用此函数,则使用用var声明的闭包变量将失败。 所以,你必须知道你做了什么。


  • 使用或不使用var命名的函数

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


  • 函数名为和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) {
            ...
        };
    ...    
}());

myFunc2myFunc1之外另外声明的myFunc1 这种形式的实现取决于Web浏览器。 它可能在使用递归函数的情况下有意义。

定义一个javascript函数

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

  1. 函数构造函数
  2. 功能声明
  3. 功能表达

功能构造函数的缺点:

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

  • 可能会阻止某些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.

功能声明的缺点:

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

功能表达的优点:

函数表达式更简单:

  • 你“只知道”它所分配的变量
  • 您无法在定义之前调用/引用为其分配函数的变量,这与其他javascript定义的一致行为

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

危险:正如“功能声明的缺点”中所提到的,这可能导致许多问题,下面是关于此的更多细节。

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

“当函数声明成为表达式的一部分不再是函数或脚本本身的”源元素“时,函数声明就不再是一个。”源元素“是脚本中的非嵌套语句或函数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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM