js中this和回调方法循环-我们到底能走多远系列(35)

我们到底能走多远系列(35)

扯淡:

  13年最后一个月了,你们在13年初的计划实现了吗?还来得及吗?

  请加油~

 

主题:

最近一直在写js,遇到了几个问题,可能初入门的时候都会遇到吧,总结下。

例子:
复制代码
var x =9;
var fobj ={
    x:1,
    test:function(callback){
        var x= 2;
        callback();
    }
}
function pp(){
    var x = 3;
    fobj.test(function(){
        alert(this.x)//9
    })
}
pp();
复制代码
上面这段代码打印出的是 9 ,可以看到test的调用者是fobj,可是在test中执行回调时callback();这调代码前面是空的。所以其实是有一个作为的全局调用了这个回调,所以,执行回调代码时的this则就是全局环境。
 
     总结一下:当方法被一个对象调用的时候:fobj.test(),那么this是绑定在fobj上的。
                    如果不是这样调用:callback() 那么this则绑定在全局变量上。
 
     回调函数中的this,最好不要使用,因为this指的是,调用函数的那个对象。
回调函数作为参数传入一个方法,我们就不能确定这个方法中的环境变量是怎样了的。
 
Function的bind方法:
复制代码
var x =9;
var fobj ={
    x:1,
    test:function(callback){
        var x= 2;
        callback();
    }
}
function pp(){
    var x = 3;
    fobj.test(function(){
        alert(this.x)//1
    }.bind(fobj))
}
pp();
复制代码
使用bind方法后输出为1,其中的this指向了fobj。
 
Array的forEach方法
在使用forEach方法的时候,也有类似的场景,这个方法提供了参数传入指定的上下文
例子:
复制代码
var x = "test";
var ojb = {
    x : "obj"
}
function pp(){
    var t = [1,2,3,4];
    t.forEach(function(value,index){
       alert(this.x + value);
    },ojb);
}
pp();
复制代码
以上代码就指定了forEach中第一个参数匿名函数的上下文为ojb。
详细的参数规则和方法使用教程:摸我
 
循环回调函数问题:
例子:
复制代码
for(var i=1;i<4;i++){
   doCallBack(function(){
       alert(i);//1,2,3
   });
}

function doCallBack(callback){
    var x = "callback";
    callback();
}    
  
复制代码
     上面的代码执行结果看似没有问题,在实际项目中,使用回调异步一些耗时工作,比如数据库的查询,写node的时候这种情况很多,那么会出现什么样的结果呢?
看下下面的模拟:
复制代码
for(var i=1;i<4;i++){
   doCallBack(function(){
       setTimeout(function(){alert(i);},1000)//4,4,4
   });
}

function doCallBack(callback){
    var x = "callback";
    callback();
}
复制代码
     全部打印4,导致这个发生的原因是因为回调函数中的耗时工作是异步的,也就是说第一次循环执行到doCallBack的时候,直接跳到for的末尾,然后开始第二次循环,一次类推,当循环达到i的最大值4的时候跳出循环,而延迟的工作开始了,这时候他们打印i,而这个i被加到了4,所以就有了全部打印4的结果。
 
先理解下js中的作用域链,比如下面的代码型式:
复制代码
function A(){
     var i =1;
     function B(){
          i =2;
          ...
     }
}
function C(){...}
复制代码
     B方法的作用域链就像这样 B内部 ->A内部 ->全局,也就是说方法内部的方法是可以引用到外部方法的变量的,如果这个B方法在C被调用,那么我们就实现C方法使用到了同级方法的作用域。其实我们就会认为这是一个闭包的行为。这样的作用域链机制,带来的副作用在前面提到的例子中展示了。
 
解决办法: 
复制代码
for(var i=1;i<4;i++){
   (function(x){
      doCallBack(function(){
        // alert(x)
         setTimeout(function(){alert(x);},1000);//1,2,3
      });
   })(i) 
}

function doCallBack(callback){
    callback();
}
复制代码
     这里我们可以看到加了个匿名方法包在外面然后直接传入i,执行方法。还利用了这个i作为基本类型是按值传递的,所以在函数内部是一个复制的值,外部i的自增将不能改变内部函数的x的值了。
 
也可以写成这样:
复制代码
for(var i=1;i<4;i++){
   !function(x){
      doCallBack(function(){
        // alert(x)
         setTimeout(function(){alert(x);},1000);//1,2,3
      });
   }(i)
}

function doCallBack(callback){
    callback();
}
复制代码
用递归的办法:感受下
复制代码
function doCallBack(x){
    if(x<=1){
       return 1;
    }else{
       setTimeout(function(){alert(x);},1000);//4,3,2
       return doCallBack(x-1);
    }
   
}
doCallBack(4)
复制代码

 

实际应用中,遇到引用类型的时候,展示使用里很土的办法先解决一下
代码类似:(3次循环,修改成下面代码)
复制代码
var rstScoreMsg0 = {
            score : scores[0],
            username : uids[0],
            expLoser : expLoser,
            expWinner : expWinner,
            uid : 0
        };
        var rstScoreMsg1 = {
            score : scores[1],
            username : uids[1],
            expLoser : expLoser,
            expWinner : expWinner,
            uid : 0
        };
        var rstScoreMsg2 = {
            score : scores[2],
            username : uids[2],
            expLoser : expLoser,
            expWinner : expWinner,
            uid : 0
        };

        recordUser(rstScoreMsg0);
        recordUser(rstScoreMsg1);
        recordUser(rstScoreMsg2);
复制代码
 
理论上,通过对象复制也是可行的。
 
 
 
 
 

让我们继续前行

----------------------------------------------------------------------

努力不一定成功,但不努力肯定不会成功。

posted on   每当变幻时  阅读(1337)  评论(1编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示