闭包和ES6的let

1.let和var定义的变量





用let声明的变量,只在let命令所在的代码块里有用.


var声明的是全局变量:




    "use strict"
    {   
        var i = 1;
        console.log(i);//1
    }  
    console.log(i);//1




用在for循环里的声明变量,最好用let。出了循环就用不了了。


2.闭包



闭包就是函数的嵌套。内层函数能使用外层函数的所有变量。哪怕外层函数已经执行完了,也照样能使用。

匿名函数

下面的例子,经过1秒后,执行forTimeout函数,
       
 
function forTimeout(x, y){
    alert(x + y);
}
function delay(x , y , time){
    setTimeout(
       function(){
          forTimeout(x , y);
      }          
      , time);   
}

delay(1, 2, 1000);


通过调试可知,delay函数先执行完,但是里面的变量x,y,time都还没释放,等待着forTimeout执行。

闭包示例1

下面这个例子:第一步,定义outer=null,执行一遍那个匿名函数,包括one的定义和赋值,inner函数的定义(此时不执行仅仅定义),让outer指向inner函数。
第二步,执行一次outer,弹出的是2;第三步,再执行一遍outer,弹出3。因为outer指向的是inner函数,对inner的引用还在,所以inner所能使用的变量和空间,都不能释放,所以它能记住上一次执行的outer

var outer = null;
(function(){
    var one = 1;
    function inner (){
        one += 1;
        alert(one);
    }
    outer = inner;
})();
outer();    //2
outer();    //3
outer();    //4


这段代码中的变量one是一个局部变量(因为它被定义在一个函数之内),因此外部是不可以访问的。但是这里我们创建了inner函数,inner函数是可以访问变量one的;又将全局变量outer引用了inner,所以三次调用outer会弹出递增的结果。


闭包示例2

再一个例子,工作中遇到过类似的问题,给一个列表元素的每一项赋相同函数的不同执行结果:


    <ul>
        <li>one</li>
        <li>two</li>
        <li>three</li>
        <li>four</li>
    </ul>


var list = document.getElementsByTagName('li');
for (var  i = 0; i < list.length; i++) {
    list[i].onmouseover = function () {
        alert(i);
    }
}


本来是想每一个li在鼠标滑过时,都弹出它们自己的下标。结果却:每个li弹出的都是4。原因是:给每个项赋值,让每一个li的onmouseover都指向一个函数,但是赋值是赋值,并没有执行这个函数啊,debugger查看可知确实没有执行。等到鼠标放上去,这才真正执行这个函数。执行的时候,发现没有i变量,那就向上找,有i,但已经变成4了,所以它们就都是4。注意,也不能在function定义后再加个(),因为这是立即执行函数了。它当下执行完,鼠标再放上去,就不执行了。真正的解决办法:
var list = document.getElementsByTagName('li');
for (var i = 0; i < list.length; i++){
    debugger;
    (function(index){
        debugger;
        list[index].onmouseover = function () {
            alert(index);
        }
    })(i);
}


还可以把希望li要进行的动作函数放在外面:
function mouseoverAction (item, index) {
    item.onmouseover = function () {
        alert(index);
    }
}
var list = document.getElementsByTagName('li');
for (var i = 0; i < list.length; i++) {
    mouseoverAction(list[i], i);
}


3.结合

注意了注意了,第一种方法其实在es6里是可以的。只需要把for循环中的var改成let,即可:

"use strict"
var list = document.getElementsByTagName('li');
for (let i = 0; i < list.length; i++) {
    list[i].onmouseover = function () {
        alert(i);
    }
}

此时,每一项确实是弹出各自的index值。for语句有个特别之处,就是:循环语句部分是一个父作用域,而循环体内部是一个单独的子作用域。同样,赋值是赋值,没有执行这个函数。等到鼠标放上去执行它,发现作用域内有这个变量i,那就弹出i。
var声明的变量,全局范围内都有效。循环改变的是var的值;而let声明的变量,只在for循环及循环体里有效





































































































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值