在定义一个函数的时候一般有两种声明方式:javascript
foo(){}; // 函数声明 var foo = function(){}; // 函数表达式
让咱们先看一个例子:css
foo(); // 函数声明 foo_later(); // foo_later is not a function function foo(){ console.log('函数声明'); } var foo_later = function(){ console.log('函数表达式'); }
能够看到,函数声明foo被预解析了,它能够在其自身代码以前执行;而函数表达式foo_later则不能。要解决这个问题,咱们先要弄清楚JavaScript解析器的工做机制。java
JavaScript解析器会在自身做用域内将变量和函数声明提早(hoist),也就是说,上面的例子其实被解析器理解解析成了如下形式:express
function foo(){ console.log('函数声明'); } // 函数声明所有被提早 var foo_later; // 函数表达式(变量声明)仅将变量提早,赋值操做没有被提早 foo(); foo_later(); foo_later = function(){ console.log('函数表达式'); }
这样也就能够解释,为何在函数表达式以前调用函数,会返回错误了,由于它尚未被赋值,只是一个未定义变量,固然没法被执行。函数
一样的,咱们也能够试着猜想下面这段代码的输出结果:spa
console.log(declaredLater); var declaredLater = "Now it's defined!"; console.log(declaredLater);
该段代码能够被解析成一下形式:code
var declaredLater; console.log(declaredLater); // undefined declaredLater = "Now it's defined!"; console.log(declaredLater); // Now it's defined!
变量声明被提到最前(因此不会报出变量不存在的错误),但赋值没有被提早,因此第一次的输出结果是undefined。blog
因为函数声明会被预解析,因此不要使用此种方法来声明不一样函数。尝试猜测下面例子的输出结果:ip
if(true){ function aaa(){ alert('1'); } } else{ function aaa(){ alert('2'); } } aaa();
与咱们预想的不一样,该段代码弹出的是“2”.这是由于两个函数声明在if语句被执行以前就被预解析了,因此if语句根本没有用,调用aaa()的时候直接执行了下面的函数。作用域
经过上面的讲解能够总结以下:
经过练习上面的实例本身多感觉一下。另外,做为最佳实践:变量声明必定要放在做用域/函数的最上方(JavaScript 只有函数做用域!)。
参考: