【javascript】 闭包函数

问题描述:做项目的时候用ajax请求从后台获取数据,根据获取到的数据在地图上循环建立marker标记。在给创建的marker添加点击事件的时候发现只能给最后一个创建的marker添加成功,尝试了几种方法,最终发现原因是data[index]在内函数中使用时不是每次循环都能取到当前的index,最后使用闭包函数解决的,写起来倒是很简单,我觉得这种东西以后会经常用到,记录一下供日后查阅。顺便学习了一下闭包函数。

错误的写法:

$.ajax({
         ...
    success:function(data){
        for(var index in data){
            //循环创建marker
            ......
            marker.addEventListener('click',function(){
                 //layer弹窗
                 layer.open({
                 content: ['http://localhost:8085/scene?sId='+data[index].sId+'','no']  
                 });
             });
        }
   }
})

正确的写法:

$.ajax({
         ...
    success:function(data){
        for(var index in data){
            //循环创建marker
            ......
          (function(i){
            marker.addEventListener('click',function(){
                 //layer弹窗
                 layer.open({
                 content: ['http://localhost:8085/scene?sId='+i.sId+'','no']  
                 });
            });
          })(index);
        }
     } 
})

下面来说说闭包

1.什么是闭包?

 闭包就是一个函数,这个函数能访问其它函数的作用域

function test(){
    var a = 1;
    var test1 = function(){
        console.log(a); //1  test1就是闭包函数,因为它能访问到test中的a
    }
    return test1;
}
test();

2.为啥它能访问到其它函数的作用域呢

从底层堆栈角度看的话,栈中存放基本变量类型和引用的对象类型变量的地址,堆中存放对象类型的变量,所以test执行顺序:

栈是先进后出表,当执行test的时候,内存会根据引用地址push进test的执行环境,当执行test1的时候,内存会push进test1的执行环境,这个时候,test1想console.log(a),内存就会从test1()的执行环境一级一级往下找,所以test执行环境中a对于test1来说是能获取到的,这也正是为什么闭包函数能获取到外部函数的作用域的原理。

3.需要注意的地方:引用的变量可能发生变化(就是我上边遇到的那种问题)

例子:

function createFunctions() {
    var result = new Array();
    for(var i=0; i<10; i++) {
        result[i] = function() {
            console.log(i);
        }
    }
    return result;
}
var result = createFunctions();
for(var i = 0;i< 10;i++){
    result[i]();       //这个时候控制台打印的是10个9 而不是0 1 2 3 4 5...
}

//调用result[i]()时工作过程
result[0] = function() { console.log(i);};
result[1] = function() { console.log(i); };
result[2] = function() { console.log(i); };

原因: 根据2的栈中的示意图,createFunctions()先执行,当执行完的时候会去result[i]的运行环境中找i,而此时i已经循环完毕变为9,所以result[i]每次打印出来的都是9.(声明一个函数的时候引擎不会对其中的变量进行赋值操作,调用的时候才去顺着运行链去找值)

正确写法:

function createFunctions() {
    var result = new Array();
    for(var i=0; i<10; i++) {
        result[i] = (function(num) {
               return function(){
                  console.log(i);
               }
          
        })(i);
    }
    return result;
}
var result = createFunctions();
for(var i = 0;i< 10;i++){
    result[i]();       //这个时候控制台打印的是0 1 2 3 4 5...
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值