平时面试常常会遇到相似下面的这种题,并且变幻无穷,让人一个头两个。示例这道题算是稍微有点难度的了,这种题考查的是JavaScript引擎执行代码的步骤。面试
b = 'cba'; function a(a, a){ console.log(a); console.log(b); var b = 'abc'; a(); function a(){ console.log(a); console.log(b); } } a(5,10);
先上理论:函数
(1)分析脚本的执行过程,也就是全局做用域下的代码。spa
①建立全局对象GO(window)code
②加载脚本代码对象
③预编译:依此找到var开头的变量声明,把变量加入到全局对象中;找到function开头的函数声明,也放到全局对象中,若是有相同的变量名或函数名,替换以前的;非声明的语句不予理睬;blog
④解释执行,变量赋值,函数调用ip
(2)分析每一个函数的执行过程作用域
①建立每一个函数对象AO(Active Object)io
②预编译:建立做用域链;初始化arguments;初始化形参,绑定arguments和形参;找到变量声明加入到AO;找到函数声明加入到AO;console
③解释执行
-----------------------------------------------------------------------------------------------------------------------------
具体分析上面的代码:
全局做用域下预编译阶段: b = 'cba';//忽略,既不是变量声明,也不是函数声明 function a(a, a){//function开头的函数声明,GO加入函数a,函数体忽略 console.log(a); console.log(b); var b = 'abc'; a(); function a(){ console.log(a); console.log(b); } } a(5,10); 全局做用域下解释执行: b = 'cba';//GO中加入变量b,且赋值为'cba' function a(a, a){ console.log(a); console.log(b); var b = 'abc'; a(); function a(){ console.log(a); console.log(b); } } a(5,10);//执行函数a,而后生成a的AO 函数a的预编译阶段: 初始化arguments; 初始化形参,两个形参名都为a,后赋的值会替换先赋的值,a先赋值为5,后赋值为10,因此此时变量a为10; console.log(a);//不是变量声明,忽略 console.log(b);//忽略 var b = 'abc';//是变量声明,将变量b加入到AO,值为undefined a();//忽略 //函数声明,函数a与形参a同名,替换以前的a=10,此时a为function function a(){ console.log(a); console.log(b); } 函数a解释执行阶段: console.log(a);//输出function console.log(b);//输出undefined var b = 'abc';//变量b赋值'abc' a();//执行,此处省略分析子函数a的预编译过程 function a(){ console.log(a); //子函数a的AO中没有变量a,向父函数a中寻找,因此输出function console.log(b); //子函数a的AO中没有变量b,向父函数a中寻找,全部输出'abc' }
有点乱哈,我写的可能也不是很清楚,不过这个真的很重要,我也是想经过这种方式能让本身加深印象,也但愿有须要的人若是看到多少能提供一点帮助。