正确内容:如果未定义,则使用 var 声明



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

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

由于maybeUndefinedfunctionargument,是否有必要标注var ?

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

示例:

function func ( arg1, arg2 ) {
    var local1, local2;
    function nested1 () {}
    function nested2 () {}
    // other code
}

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

  • __arg1
  • 最长
  • local1
  • local2
  • nested1
  • nested2
  • 参数

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

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

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

func(123);

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

顺便说一句,如果您使用严格语言(推荐!),函数环境是static,这意味着上述绑定保证是函数环境中唯一的绑定。另一方面,默认语言提供了某些机制,以便动态地从函数环境中添加/删除绑定。例子:
(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
}());

您不应该再次使用var,它不利于可读性,并且作为参数的变量已经在局部范围内。

另外,您应该注意它不是this的一部分。只有在使用了new关键字的情况下,this才会被限定在函数对象的范围内,并且由于没有命名函数,因此在这种情况下似乎不太可能。如果没有new, this指的是window(如果使用use strict;,则是undefined),由于参数具有局部作用域,您的变量肯定不是其中的一部分。

接口

包含函数参数实际上与限定变量的作用域相同(换句话说,它实际上与使用 var 关键字定义函数级引用相同)。提供函数参数(在JavaScript中)的主要原因是为了满足您自己的接口偏好。

arguments对象

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

// The following functions do the same thing, but one is "more readable"
function foo() {
  return arguments;
}
function bar(baz, qux) {
  return arguments;
}

求值(接口)vs执行(实现)

当两个函数都求值时(在文件'load'上),arguments对象在每个函数定义中都是undefined;直到函数执行了其中的代码,对象才被"定义";为了使使用伪代码可视化,它看起来像这样:

// 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()
}

函数调用

所以当你调用一个函数时,它"实现"或"执行"它的(它的"对象")。当它这样做时,如果已经被压入 arguments 对象的对象被定义,则函数可以引用它们。如果没有,将抛出一个引用错误,并记录变量在该范围内为undefined

简而言之:

没有必要使用 var 来连接函数作用域级变量(又名"私有成员"),因为语言已经将arguments对象附加到所有function主体对象上。

更多阅读:

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

最新更新