请说明一下对这一段JavaScript的理解,主要包括引擎、编译、执行、做用域、异常这些要点。而后猜想下会输出那些内容。函数
var hello = null; var b = 2; foo(3); console.log(c); function foo(a){ try{ console.log(c); }catch(error){ console.log(error); } try{ hello(); }catch(error){ console.log(error); } c = a*b; console.log(a+b); }
/* 1.编译器遇到 var hello这个声明语句,就在当前做用域中声明变量hello(当前做用域没有变量hello,这里当前做用域就是全局做用域)。 */ var hello = null; var b = 2; foo(3); console.log(c); /* 1.编译器在当前做用域把foo声明成一个函数,同上 2.在函数的内部做用域声明a变量 */ function foo(a){ try{ console.log(c); }catch(error){ console.log(error); } try{ hello(); }catch(error){ console.log(error); } c = a*b; console.log(a+b); }
编译器会先找到全部的声明(var xxx,function xxx这些才是声明),而后在对应的做用域中建立该变量/函数,若是该声明不存在的话。这个过程叫‘提高’。code
/* 1.运行时读取到的是hello = null,首先在做用域链中查找hello,找到的话执行赋值操做 */ var hello = null; var b = 2; /* 1.在做用域链中找foo而且执行它,这里隐式地执行了a = 3,这里的a其实是foo函数做用域里声明的一个变量 2.以后转入函数内部执行 */ foo(3); /* 0.在函数执行完毕后,执行到这儿 1.在做用域中查找console这一变量,而后找到了,而后获取它的log属性,而后把它做函数执行 2.隐式地执行了x = c,在当前做用域中查找c,能找获得吗? */ console.log(c); function foo(a){ try{ //尝试在做用域链中找c,找到本函数做用域-->全局做用域都没找到,因而抛出异常ReferenceError,这个异常就是在做用域链中找不到某变量但又须要知道它的值出现的,咱们须要输出c的值 console.log(c); }catch(error){ console.log(error); } try{ //尝试在做用域链中找hello,在全局做用域找到了,把它当函数执行,但它不是函数,因而抛出异常TypeError,这个异常就是找到了,可是使用方法不对 hello(); }catch(error){ console.log(error); } //先计算a*b,在做用域链中找a和找b的值,而后执行c=6,又开始找c,想要给c赋值,找到头也找不到,因而自动地在全局做用域下声明了一个c,而后执行c=6,注意这里咱们不关心c的值 c = a*b; console.log(a+b); }
js的做用域是词法做用域,就是说变量处于哪一个做用域是由代码怎么写决定的,在编译期间肯定。
做用域链就像个大楼,查找变量的时候从当前楼层查到顶楼(全局)为止ip
经过这段代码可大体理解js引擎在编译阶段作了什么,在执行阶段又怎么作,做用域在这两个阶段中起到什么做用(中间者,管家)。两个很是常见的异常是在什么状况下发生的。
・゜゚・:.。..。.:・'(゚▽゚)'・:.。. .。.:・゜゚・作用域
参考书籍《你不知道的JavaScript(上卷)》第一部分,亚马逊电子书9.9元,强力推荐编译器