定义在词法阶段的做用域,开始时,编译器作语法分析的时候,确认js里各个词法所在的做用域。
js里只有全局做用域和函数做用域,这里简单介绍下js的做用域。异步
看下面代码:函数
var a = 1; var b = 0; function foo() { var a = 2; console.log(a); //2 console.log(b); //0 } foo(); console.log(a); //1
一、在foo函数里,在console.log(a),对a进行RHS查询,发如今当前做用域存在变量a,若是foo里没有a就往上一层(全局)去查找
二、在foo函数里,在console.log(b),对b进行RHS查询,发如今当前做用域不存在变量b,而后往上一层(全局)去查找b,发现存在变量b,获取b的值。code
在词法分析阶段,会确认在全局做用域里有a,b这两个变量,函数foo做用域里有a这个变量对象
可是,有些方法能够欺骗或者动态生成做用域。作用域
例如:eval、setTimeout、with等字符串
eval函数能够理解为在当前做用域插入一段代码。编译器
以下:it
var b = 2; function foo() { eval('var b=1') console.log(b); //1 } foo(); console.log(b); //2
在开始的词法分析中,foo函数做用域并不存在变量b,然而在引擎执行代码的时候,到eval函数执行,就强行在foo函数做用域中插入变量bio
setTimeoutconsole
定时器函数是一个异步函数,第一个参数中字符串的执行做用域是全局做用域,相似上面动态插入变量。
var b = 1; function foo() { setTimeout('var b =2', 0); setTimeout('console.log(b)', 0); //2 } foo(); console.log(b); //1
with
扩展一个语句的做用域链。
在一个对像是扩展属性,若是属性存在就修改属性值,若是不存在就挂载在全局对象上,相似于在函数里不用var声明的变量都挂在window对象上。