三:作用域链
先来看一段代码:
- name="lwy";
- function t(){
- var name="tlwy";
- function s(){
- var name="slwy";
- console.log(name);
- }
- function ss(){
- console.log(name);
- }
- s();
- ss();
- }
- t();
当执行s时,将创建函数s的执行环境(调用对象),并将该对象置于链表开头,然后将函数t的调用对象链接在之后,最后是全局对象。然后从链表开头寻找变量name,很明显
name是"slwy"。
但执行ss()时,作用域链是: ss()->t()->window,所以name是”tlwy"
下面看一个很容易犯错的例子:
- <html>
- <head>
- <script type="text/javascript">
- function buttonInit(){
- for(var i=1;i<4;i++){
- var b=document.getElementById("button"+i);
- b.addEventListener("click",function(){ alert("Button"+i);},false);
- }
- }
- window.onload=buttonInit;
- </script>
- </head>
- <body>
- <button id="button1">Button1</button>
- <button id="button2">Button2</button>
- <button id="button3">Button3</button>
- </body>
- </html>
当文档加载完毕,给几个按钮注册点击事件,当我们点击按钮时,会弹出什么提示框呢?
很容易犯错,对是的,三个按钮都是弹出:"Button4",你答对了吗?
当注册事件结束后,i的值为4,当点击按钮时,事件函数即function(){ alert("Button"+i);}这个匿名函数中没有i,根据作用域链,所以到buttonInit函数中找,此时i的值为4,
所以弹出”button4“。
四:with语句
说到作用域链,不得不说with语句。with语句主要用来临时扩展作用域链,将语句中的对象添加到作用域的头部。
看下面代码
- person={name:"yhb",age:22,height:175,wife:{name:"lwy",age:21}};
- with(person.wife){
- console.log(name);
- }
with语句将person.wife添加到当前作用域链的头部,所以输出的就是:“lwy".
with语句结束后,作用域链恢复正常。