js是依靠作用域链来进行运行的,上一篇讲了作用域运行的机制,现在来讲讲作用域和作用域链。
全局作用域
js的最外层函数,和最外层定义的变量都拥有全局作用域。下面看一个例子:
var authorName="山边小溪";
function doSomething(){
var blogName="梦想天空";
function innerSay(){
alert(blogName);
}
innerSay();
}
alert(authorName); //山边小溪
alert(blogName); //脚本错误
doSomething(); //梦想天空
innerSay() //脚本错误
还有一点是未定义直接赋值的变量自动被提升为全局变量比如:
function doSomething(){
var authorName="山边小溪";
blogName="梦想天空";
alert(authorName);
}
doSomething(); //山边小溪
alert(blogName); //梦想天空
alert(authorName); //脚本错误
再就是window属性具有全局作用域,这就引出下面的document的例子了:
function changeColor(){
document.getElementById("btnChange").onclick=function(){
document.getElementById("targetCanvas").style.backgroundColor="red";
};
}
```,
这里的document就是全局作用域,标志符的位置越深,执行的效率就会越慢,因此因为document处于运行期上下文的最末端,所以查找起来最慢,所以要少用全局变量,尽可能多的使用局部变量,这里有一个经验就是一个跨作用域的变量使用了两次以上就要把他保存在局部变量中,例如下面的代码:
<div class="se-preview-section-delimiter"></div>
这里写代码片
“`
function changeColor(){
document.getElementById("btnChange").onclick=function(){
document.getElementById("targetCanvas").style.backgroundColor="red";
};
}
把他改为:
function changeColor(){
var doc=document;
doc.getElementById("btnChange").onclick=function(){
doc.getElementById("targetCanvas").style.backgroundColor="red";
};
}
还有一点是少用with,虽然with可以省代码,但是他会有另外一个作用域链,不利于性能,因此不推荐使用。
还有一个就是try{}catch(){}语句,当try中的语句发生错误时,执行语句会跳到catch中,把异常对象推入一个可变对象的,并置于作用域链头部,在catch中所有的局部变量将会被推到第二个作用域链中,头部就就是最末端的作用域。但是try{}catch(){}对于错误处理是很好的,所以我们要这样改进:
try{
doSomething();
}catch(ex){
handleError(ex); //委托给处理器方法
在这里只执行一条语句,就不存在局部作用域链的访问,因此作用域链的临时改变就不会影响代码性能了。