JavaScript变量作用域与闭包实现

先抛出原问题:

for (var i = 0; i < 10; i++) {
divs[i].onmouseover = function () {
    this.style.backgroundColor = "red";
    this.style.left = -55*i;
    };
}

测试结果显示:鼠标经过所有div时,北京颜色会变成红色,但是所有div的定位都为-55*10!这就是问题所在!

正好在JS闭包理解上还不是很通透,为找出问题所在,特意写了一个小小的demo:

<!DOCTYPE html>
<html>
<body>
<div id="header">
<p id="p">This is a word!</p>
</div>
</body>
<script type="text/javascript">  
p.onclick = function() {
var header = document.getElementById('header');
var p = document.getElementById('p');
// 生成十个测试的span
for (var i = 0; i < 10; i++) {
    var ele_span = document.createElement("span");
    ele_span.id = "id_" + i;
    ele_span.innerHTML = "This is" + i + "span";
    header.appendChild(ele_span);
};
var spans= document.getElementsByTagName("span");
for (var i = 0; i < 10; i++) {
    spans[i].onmouseover = function () {
        console.log(i);
        console.log(this);
        this.style.backgroundColor = "red";
    }
    document.getElementById("id_"+i).onclick = function(i) {
        console.log(this);
        console.log(i);
        this.style.backgroundColor = "green";
    }
};
}
</script>
</html>

点击段落,生成十个span,id从1~10,接着通过for循环为每个span绑定mouseover以及click事件,鼠标经过每个元素时,背景颜色变成红色,但是console.log(i)输出永远都是10。结果如图:

233036_7w4w_782868.png

那试着把i通过参数传递到click绑定函数呢?情况会怎样?如果你认为console.log(i)会输出相应的i值,那你就被参数i骗了!参数i只是一个参数名,想写成啥写啥,不过一般的写法都是e,以为绑定事件,传递到时间函数的参数是事件本身,有图有真相:

233036_Jlec_782868.png

这样的话,想通过这样把参数i值传递到时间函数里是没门了。这时候,闭包的功力就立体现了:

for (var i = 0; i < 10; i++) {
    document.getElementById("id_"+i).onclick = (function (i) {
        console.log(i);
    })(i);
};

测试结果如下:

233037_gngE_782868.png

从结果可以看出,匿名函数自动执行,而且每次循环的i值传递到匿名函数里,这样就实现值传递了。

画个小图理解思路:

233037_ndgi_782868.png

JavaScript也采用此法作用域,函数执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是调用时决定的。局部变量作用域具有局部性的,当JavaScript需要查找变量i时,先查找本作用域,这里就是先查找事件函数,如果没有查找到,就往上查找外部对象,这里就查找到for循环里的变量,此时找到了,就取得i的值,但此时i的值已经自增到10,所以console.log(i)输出10;JavaScript变量查找通过变量的作用域查找,不断往顶层作用域查找,直到global对象,如果在global对象中还没有查找到变量,就会抛出引用错误(ReferenceError)异常。

这就是JavaScript变量作用域的特性的,可以通过闭包实现变量保存在函数作用域中。

转载于:https://my.oschina.net/No5stranger/blog/210496

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值