js中作用域与作用域链
作用域
*作用域基本概念
作用域一般指变量的作用范围,变量分为全局变量和局部变量,对应的作用域就分别是全局和函数作用域。
示例1
var scope="global";
function t(){
console.log(scope);
var scope="local"
console.log(scope);
}
t();
//此处打印结果是undefine local 此处有坑,正常理解 第一个应该打印出来global ,因为scope全局变量,但是js中有个声明提前,这个代码可以解读为示例2,看不懂的出去哭会
示例2
var scope="global";
function t(){
var scope;
console.log(scope);
scope="local"
console.log(scope);
}
t();
//进入函数中,变量声明提前,第一次打印出来的依然是局部变量,只不过没有赋值,所以是undefine,
示例3
var name="global";
if(true){
var name="local";
console.log(name)
}
console.log(name);
//正常思路:内部打印local,外部打印global,恭喜你掉坑里了,全部是local,js只有全局与函数作用域 if中的声明覆盖了全局变量都打印出来local
作用域链
简单说就是函数里调用函数1,函数1里调用函数2,那么就有了这么一个作用域链全局作用域==>函数1作用域==>函数2作用域;特点是函数1里面可以直接使用全局作用域的变量,函数2里面可以直接使用全局作用域和函数1作用域的变量
示例1
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"
示例2
<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;这是因为点击事件是在html加载之后才触发的 此时匿名函数没有i需要逐级向上查找,找到循环体此时i已经是4