JavaScript Hoisting
先给一个高大上的术语「JavaScript Hoisting」——没听过的人可能是一头雾水,理解的人则可能会心一笑。hoist是提升的意思(百度翻译):
1 | hoist: |
但知道这个单词可能无助于理解这个术语。但一贯地,我认为概念可以提纲契领,所以定义先来:
Hoisting is JavaScript’s default behavior of moving all declarations to the top of the current scope (to the top of the current script or the current function).
在js中,解释器默认会把所有的(变量/函数)声明提升到当前作用域的顶部,这就叫hoisting。
Variable Hoisting
1 | // ReferenceError: undefinedVariable is not defined |
当我们访问未定义的变量时,会报ReferenceError,这很正常,再看:
1 | console.log(definedBelowVariable); // output --> undefined |
看到这段代码的输出,这一小节要讲的Variable Hoisting
已经清晰了。在js中,变量的声明可以在使用之后,换句话说,变量可以先使用再声明。但注意:变量的初始化不会提升(hoisting)。
所以上面的代码相当于:
1 | var definedBelowVariable; // Variable Hoisting |
Function Hoisting
js中函数定义(define)要用function
关键词,定义有两种方式:函数声明或者函数表达式。
函数声明(function declaration)
1
2
3function functionName(parameters) {
code to be executed
}函数表达式(function expression)
1
var x = function (a, b) {return a * b};
了解了函数定义的两种方式,再从例子中看函数提升。
1 | isItHoisted(); // Outputs: "Yes!" |
很显然,函数被提升了,即函数定义可以在函数使用之后。但请注意:Function Hoisting仅适用于使用函数声明方式定义的函数。这是我要分开讲变量提升和函数提升的一个重要原因。
1 | // Outputs: "Definition hoisted!" |
从上面的代码中可以看出:definitionNotHoisted
的声明被提升了,所以是undefined
;但函数定义没有提升,所以是TypeError
。
你可能想知道当你使用命名的函数表达式会怎么样:
1 | // ReferenceError: funcName is not defined |
显然,当命名的函数作为函数表达式的一部分时,不会被提升。
参考:
- http://designpepper.com/blog/drips/variable-and-function-hoisting
- http://www.w3schools.com/js/js_function_definition.asp
- http://www.w3schools.com/js/js_hoisting.asp
- http://stackoverflow.com/questions/26542361/javascript-scopes#26542456