1.函数作用域
所谓函数作用域就是说:-》变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。
var scope="global"; function t(){ console.log(scope); var scope="local" console.log(scope); } t();
第一句输出的是: "undefined",而不是 "global",因为js采用函数作用域,scope在函数t中重新声明了,则在整个函数t中都有效,覆盖了全局的声明,但第一句时还未赋值,所以是undefined- 第二讲输出的是:"local"
-
等价代码:
var scope="global"; function t(){ var scope; console.log(scope); scope="local" console.log(scope); } t();
二:变量作用域
Js中没有用var声明的变量都是全局变量,而且是顶层对象的属性。用console.log(window.s)也是会输出“ifscope"
- function t(flag){
- if(flag){
- s="ifscope";
- for(var i=0;i<2;i++)
- ;
- }
- console.log(i);
- }
- t(true);
- console.log(s);
- 会输出:”ifscope"
当使用var声明一个变量时,创建的这个属性是不可配置的,也就是说无法通过delete运算符删除
var name=1 ->不可删除
sex=”girl“ ->可删除
this.age=22 ->可删除
三:作用域链
slwy tlwyname="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()->window 将创建函数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.οnlοad=buttonInit; </script> </head> <body> <button id="button1">Button1</button> <button id="button2">Button2</button> <button id="button3">Button3</button> </body> </html>
当文档加载完毕,给几个按钮注册点击事件,当我们点击按钮时,会弹出什么提示框呢? 很容易犯错,对是的,三个按钮都是弹出:"Button4",你答对了吗? <span style="color:#ff0000;">当注册事件结束后,i的值为4,当点击按钮时,事件函数即function(){ alert("Button"+i);}这个匿名函数中没有i,根据作用域链,所以到buttonInit函数中找,此时i的值为4,</span>所以弹出”button4“。