红宝书原文
某些语句会导致在作用域链前端临时添加一个上下文,这个上下文在代码执行后会被删除。 两种情况会出现这个现象: 1、try/catch语句的catch块 2、with语句
- try/catch语句的catch块:会创建一个新的变量对象,这个变量对象会包含要抛出的错误对象的声明。
- with语句:会向作用域链前端添加指定的对象。
前置知识
- 作用域链:决定了各级上下文中的代码在访问变量和函数时的顺序。代码正在执行的上下文的变量对象始终位于作用域链的最前端。
- 在代码预解析阶段,在每一个作用域中(全局作用域/函数作用域),会确定该作用域的作用域链。
- 在代码执行阶段,执行上下文会依次被推入进执行栈中,当一个函数上下文执行完毕之后,会被推出执行栈。
情况一:with语句
function buildUrl(){
let qs="?debug=true"
with(location){
let url=href+qs
return url
}
}
console.log(buildUrl()) //https://code.devrank.cn/preview?projectId=7391306329702793253?debug=true
在以上代码块中,with()中的变量location是全局变量,应该放在全局上下文中,当使用到location这个变量时,应该是一直沿着作用域链往外检索,直到检索到全局作用域时,直到这个变量,并使用。但由于使用了with语句,会进行作用域链增强,因此location会被添加到作用域链最前端,如图所示:
在开发中我们应该尽量减少with语句的使用
因为with语句会使作用域链被加长,除了被添加到最前端的变量外,其他变量标识符解析的性能都会变差!