作用域与闭包
1.作用域
几种常常容易误解的例子
<script type="text/javascript">
alert(a); // undefined 声明提前
var a = 20;
</script>
//所有的全局变量的声明都会提前到JavaScript的前端声明。也就是所有的全局变量都是先声明的,并且早于其他一切代码。但是变量的赋值的位置并不会变,仍然在原位置赋值
//以上代码等同于
<script type="text/javascript">
var a; //声明提前
alert(a);
a = 20; //赋值仍在原来的位置
</script>
--------------------------------------------------------
var a=10;
if(a>20){
var b=20;
}
console.log(b); //undefined 声明提前,不然就会报错*/
--------------------------------------------------------------------------------------------
var a = 10;
function foo(){
cnosole.log(a); //访问的是局部变量,声明提前
var a = 20;
}
foo(); //undefined
--------------------------------------------------------------------------------------------
var a = 10;
function foo(){
console.log(a); //10
a = 20;
console.log(a); //20
}
foo();
--------------------------------------------------------------------------------------------
console.log(a); //报错
console.log(typeof a) //undifined,虽然没有声明
function foo(){
a = 20;
}
foo(); //执行后,没有定义的a会自动变成全局变量
console.log(a); //访问全局变量 结果为undefined
--------------------------------------------------------------------------------------------
2.闭包
闭包
广义的闭包:
一个函数访问了它外部的变量
狭义的闭包:
如果一个函数,访问了它的外部变量函数的局部变量,那么这个函数就是一个闭包
闭包的特点:
闭包可以访问它的外部函数作用域内的任何的变量,而且访问到的变量的值一定是最新的值,
即使外部函数执行结束,也仍然可以访问外部函数的局部变量
var a =10;
function foo(){
var a =20;
function inner(){
console.log(a);
}
a =30;
return inner;
}
var f = foo();
f(); //30
使用闭包封装对象
function foo(){
var p = { //将对象放入函数中,使得对象无法被更改
name : "Tom",
age : 22
}
return {
getName : function(){
return p.name;
},
getAge : function(){
return p.age;
},
setName : function(name){
return p.name = name;
},
addAttr : function(key,value){
return p[key] = value;
}
}
}
var f = foo();
f.getName() //"Tom"
for循环的经典问题
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<script type="text/javascript">
var btns = document.querySelectorAll("button");
//解决方案一:匿名函数的自调用
for (var i=0; i<btns.length; i++){
// 匿名函数自调用
btns[i].onclick = (function(i){
return function(){
alert(i);
}
})(i)
//解决方案二: 利用属性存储i的值
btns[i].index = i;
btns[i].onclick = function(){
alert(this.index);
}
}
//解决方案三:利用ES6的新方法,let
for (let i=0; i<btns.length; i++){
btns[i].onclick = function(){
alert(i);
}
}
</script>
</body>
</html>