什么是正确的:var声明,如果未定义

时间:2013-05-29 20:45:22

标签: javascript

在这样的情况下,我听到了关于var用法的不同意见:

function(maybeUndefined) {
    if(typeof maybeUndefined === 'undefined')
        var maybeUndefined = 'bob';
}

是否有必要注明var,因为maybeUndefinedargument的{​​{1}}?

4 个答案:

答案 0 :(得分:10)

在这种情况下,您不需要var,因为mayBeUndefined已经在函数范围内分配(提示:函数定义中的列出参数变量会导致这些变量在本地声明) 。因此,var完全是可选的,尽管完全没有意义(并且可读性消耗殆尽)。

答案 1 :(得分:6)

示例:

function func ( arg1, arg2 ) {
    var local1, local2;

    function nested1 () {}
    function nested2 () {}

    // other code
}

这里我们有一个函数声明。将此声明解析为函数对象时,将使用以下绑定为该函数创建词法环境(= scope):

  • ARG1
  • ARG2
  • LOCAL1
  • local2
  • nested1
  • nested2
  • 参数

(请注意,还有两个特殊的内置绑定:thisarguments。这些绑定总是为所有函数对象创建。)

这些名称被定义为本地绑定。 (此过程在"Declaration binding instantiation"中指定。警告:此算法不应由人类:-)读取。因此,当名称被定义为参数时,没有必要将其声明为局部变量。此机制与调用函数时是否为该参数传递值(参数)无关。

所以,即使你像这样调用函数:

func(123);

名称arg2仍将被定义(作为函数环境中的绑定),尽管其特定调用的值最初为undefined

顺便说一句,如果你使用严格语言(推荐!),函数环境是静态,这意味着上述绑定被保证是函数中唯一的绑定环境。另一方面,默认语言提供了某些机制,动态,添加/删除功能环境中的绑定。例如:

(function () {

    // the name "temp" does not exist as a binding in the function's environment

    eval('var temp');

    // now it does

    delete temp;

    // and it's gone again

}());

答案 2 :(得分:3)

你不应该再次使用var,这对于可读性是不利的,并且变量将因为作为参数而在本地范围内。

另外,您应该注意它不是this的一部分。如果使用this关键字,new只会限定为函数对象,并且由于您没有命名函数,在这种情况下似乎不太可能。如果没有new,this引用窗口(如果使用undefined则为use strict;),其变量绝对不是参数具有局部范围的结果。

答案 3 :(得分:1)

<强>接口

包含函数参数实际上与作用变量的范围相同(换句话说,它与使用 var 关键字定义函数级引用实际上是相同的)。提供函数参数(在JavaScript中)的主要原因是您自己的接口首选项。

arguments对象

参数仍然可以传递给没有参数的函数,并且仍然可以在'hidden'arguments对象中访问 - 这是一种“伪数组”(如果你愿意的话),因为它在功能上是一个数组,但没有配备相同的API JavaScript Array(伪类型)配备:

// The following functions do the same thing, but one is "more readable"

function foo() {
  return arguments;
}

function bar(baz, qux) {
  return arguments;
}

评估(界面)与执行(实施)

当两个函数都评估(在文件'load'上)时,arguments对象在每个函数定义中都是undefined;在函数 body 执行其中的代码之前,对象不会被“定义”;要使用伪代码可视化,它看起来像这样:

// Function bodies (as objects)
foo : {
  arguments : new Array // [undefined]
  __proto__ : Empty() // the super-object that allows this object to inherit "functionality"
}

bar : {
  arguments : new Array(baz, qux) // [undefined, undefined]
  __proto__ : Empty()
}

功能调用

因此,当您调用某个函数时,它会“实现”或“执行”其 body (其“对象”)。当它这样做时,如果已经定义了推入 arguments 对象的对象,则该函数可以引用它们。如果不是,则抛出引用错误,记录该范围内的变量undefined

简而言之:

没有必要使用 var 来连接功能范围级变量(也称为“私有成员”),因为该语言已将arguments对象附加到所有function身体对象。

更多阅读:

JavaScript Memoization:“函数缓存”多个参数以获得更好的性能: http://decodize.com/javascript/javascript-memoization-caching-results-for-better-performance/

相关问题