foo(); // TypeError "foo is not a function"
bar(); // valid
baz(); // TypeError "baz is not a function"
spam(); // ReferenceError "spam is not defined"
var foo = function () {}; // 匿名函数表达式('foo'被提升)
function bar() {}; // 函数声明('bar'和函数体被提升)
var baz = function spam() {}; // 命名函数表达式(只有'baz'被提升)
foo(); // valid
bar(); // valid
baz(); // valid
spam(); // ReferenceError "spam is not defined"
How to Code With This Knowledge
现在你明白了作用域和提升,那么这对编写JavaScript代码意味着什么呢?最重要的一条是声明变量时总是使用var语句。我强烈的建议你在每个作用域中都只在最顶端使用一个var。如果你强制自己这么做,你永远也不会被提升相关的问题困扰。尽管这么做会使的跟踪当前作用域实际声明了哪些变量变得更加困难。我建议在JSLint使用onevar选项。如果你做了所有前面的建议,你的代码看起来会是下面这样:
复制代码 代码如下:
/*jslint onevar: true [...] */
function foo(a, b, c) {
var x = 1,
bar,
baz = "something";
}
What the Standard Says
我发现直接参考ECMAScript Standard (pdf)来理解这些东西是如何运作的总是很有用。下面是关于变量声明和作用域的一段摘录(section 12.2.2):
If the variable statement occurs inside a FunctionDeclaration, the variables are defined with function-local scope in that function, as described in section 10.1.3. Otherwise, they are defined with global scope (that is, they are created as members of the global object, as described in section 10.1.3) using property attributes { DontDelete }. Variables are created when the execution scope is entered. A Block does not define a new execution scope. Only Program and FunctionDeclaration produce a new scope. Variables are initialised to undefined when created. A variable with an Initialiser is assigned the value of its AssignmentExpression when the VariableStatement is executed, not when the variable is created.
我希望这篇文章能够给JavaScript程序员最容易困惑的部分一些启示。我尽力写的全面,以免引起更多的困惑。如果我写错了或是漏掉了某些重要的东西,请一定让我知道。
您可能感兴趣的文章: