总结下js的加载到执行,浏览器都做了什么,如何形成js函数作用域链。
看下面的代码:
<script>
function addEvents(){
var id = “form1”;
document.getElementById(“save_button”).onclick = function(event){
sumitForm(id);
};
}
</script>
函数加载到页面,浏览器开始解释
add函数被创建,浏览器将add可访问的作用域的对象放入add的[[scope]]①属性中,供函数执行时候用。
addEvent ();
函数执行时候,浏览器会做一些准备
1、 浏览器会创建一个运行期上下文(类似编译原理所说的运行栈),用于定义函数执行时的环境,当函数执行完毕就会删除。
2、 浏览器将addEvent的scope属性复制到上下文的作用域链scope chain中。
3、 浏览器根据addEvent创建一个活动对象,该对象类似map键值对,包含了addEvent函数的局部变量,并将活动对象放入作用链数组的最顶层。
如图:
这里可以看到很多东西,例如
1、访问局部变量比全局变量速度快。
2、因为局部变量在作用域链的顶端,在函数中将频繁使用的全局变量赋值给局部变量,可提供程序执行的时 间。
3、With语句改变作用域链,是将一个对象放入作用域链的最顶端,这样访问with语句的对象很快,但是访问局部变量就慢了一个级了。不推荐使用with语句,因为可以将对象赋值给局部变量,访问速度也很快,节省了改变作用域链的消耗。
4、With、eval、catch子句,他们都可以改变作用域链,令到一些对访问变量进行优化的引擎没法正常优化 ,因为可以将对象赋值给局部变量,访问速度也很快,节省了改变作用域链的消耗。
(待续 下篇 闭包作用域链)