关于var
在这种情况下的使用,我听到了不同的意见:
function(maybeUndefined) {
if(typeof maybeUndefined === 'undefined')
var maybeUndefined = 'bob';
}
由于maybeUndefined
是function
的argument
,是否有必要标注var
?
在这种情况下不需要var
,因为mayBeUndefined
已经在函数范围内分配了(提示:在函数定义中列出参数变量会导致局部声明这些变量)。因此,var
是完全可选的,尽管完全没有意义(并且会降低可读性)。
示例:
function func ( arg1, arg2 ) {
var local1, local2;
function nested1 () {}
function nested2 () {}
// other code
}
这里有一个函数声明。当将此声明解析为函数对象时,将为该函数创建具有以下绑定的词法环境(= scope):
- __arg1
- 最长
- local1
- local2
- nested1
- nested2 参数
(注意还有两个特殊的内置绑定:this
和arguments
。它们总是为所有函数对象创建的。)
这些名称被定义为本地绑定。(此过程在"声明绑定实例化"中指定。警告:这个算法是不被人类读取的(:-)
)因此,当一个名字被定义为参数时,没有必要将其声明为局部变量。此机制与调用函数时是否为该形参传递值(实参)无关。
所以,即使你像这样调用函数:
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
}());
您不应该再次使用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/