关于作用域
JS会在执行之前编译,并采取相应优化例如JIT优化;编译分为分词、语法分析、代码生成过程。
而作用域是关于变量(或是标识符)去何处查询以及如何查询的一套规则。分为RHS、LHS查询,RHS找到对应位置且要返回值,LHS查询会找到对应的空间。LHS在非严格模式下在无法找到的情况下在全局对象中建立变量且返回,严格模式下会出错“Reference Error”。简而言之,reference error是作用域判别失败,typeerror是作用域判别成功但是执行操作不当。
作用域包括函数作用域、块级作用域。利用函数作用域可以用来隐藏信息,避免命名冲突(可以为一个编译单元使用一个统一的命名空间,可以使用模块的方式)。但是用函数来封装的问题是什么呢?第一,它会污染作用域;其次,还要显示的调用。那就可以使用IIFE了。
1、函数表达式与函数声明的区别,主要是语句开头的词法单元是不是"function"。若是表达式则可以用()(),(())不同的调用模式了。
2、函数声明是不可以匿名的,函数表达式可以。
匿名函数问题: 1、在栈追踪的调试上比较困难;2、在递归运算时不得不使用arguments.callee这种过时的技术。
IIFE作用:1、可以避免污染作用域以及不用显示调用;
2、可以使用所谓的UMD模式。见下面:
var a = "demo string"; (function (def) { def(window); }(function (global) { console.log(global.a); //"demo string"; }));
第二部分
块级作用域
1、with. 它会将with限定的obj添加到其后代码块的标识符的作用域的前端。
2、try/catch的catch分句(es3中就有)。用于在不支持let语句条件下人为建立一个块级作用域。
//let 语句形式 let a = 3; console.log(a); //catch的实现 { try { throw 3; } catch (a) { console.log(a); } }
google支持一个叫做Traceur的项目,将ES6的代码向转为可以向下兼容的形式。
3、let.let不会提升变量,在垃圾收集、闭包(多是循环等)中有重要的作用。
4、const。这个是建立块级的常量。
{ const a = "inner"; console.log(a); //"inner" } console.log(a); //reference error;