function getXHR() {
      if (typeof XMLHttpRequest != "undefined") {
        return new XMLHttpRequest();
      }
      try { return new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch(e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch(e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP") } catch(e) {}
      try { return new ActiveXObject("Microsoft.XMLHTTP") } catch(e) {}
      return null;
    }
function TestObject(user)
{ this.m_user = user; this.m_req = getXHR();
if (!this.m_req) throw ""; this.m_req.onreadystatechange = function()
{
                  //这里this.readyState在ie6是未定义,ie8居然可以,到该应该怎么写这里?
if (this.readyState == 4)
{
//还有这里,我想取得变量TestObject.m_user
var o = this.m_user;//这样写也不对,应该怎么写, alert(o.m_user + " done"); }
}
}TestObject.prototype.logIn = function()
{ try { var url; url = "http://www.baidu.com/"; this.m_req.open('GET', url, true);   this.m_req.send();
} catch (ex) { }}
    function main() {      var o1 = new TestObject("aaaaa");
  o1.logIn();
     var o2 = new TestObject("bbbbb");
  o2.logIn();
    }
main() ;

解决方案 »

  1.   


           //这里this.readyState在ie6是未定义,ie8居然可以,到该应该怎么写这里?
            //IE6这里的this指的是window对象,当然不行了
            if (this.readyState == 4)
            {
                //还有这里,我想取得变量TestObject.m_user
                var o = this.m_user;//这样写也不对,应该怎么写,            alert(o.m_user + " done");        }    //使用闭包把this对象包进去就好了
        this.m_req.onreadystatechange = (function(that){return function()
        {
            if (that.m_req.readyState == 4)
            {
              var o = that.m_user;            alert(o + " done");        }
            that.m_req = null;
           that = null;
        }
        })(this);
      

  2.   


    给你闭包了后,send的时候都发生异常了,这闭包的代码也真不好看
      

  3.   

    这样改,更简单更容易理解些function TestObject(user)
    {    this.m_user = user;    this.m_req = getXHR();
        if (!this.m_req)    throw "";
        var _this=this;  //这里用一个变量来代替this
        this.m_req.onreadystatechange = function()
        {
           //这里this.readyState在ie6是未定义,ie8居然可以,到该应该怎么写这里?
            if (_this.readyState == 4)  //在这里,用_this 代替 this
            {
                //还有这里,我想取得变量TestObject.m_user
                var o = _this.m_user;//这样写也不对,应该怎么写,            alert(o.m_user + " done");
            }
        }
    }
      

  4.   

    试过就知道,这样做其实是有道理的你的请求是异步的,所以当onreadystatechange 发生的时候,TestObject函数其实早已运行结束
    所以onreadystatechange发生的时候,此时的this已经不是你所认为的原来那个对像了,而应该是m_req,也就是httprequest对象所以用一个变量来保存this的引用,这样就正确了
      

  5.   

    function getXHR() {
          if (typeof XMLHttpRequest != "undefined") {
            return new XMLHttpRequest();
          }
          try { return new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch(e) {}
          try { return new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch(e) {}
          try { return new ActiveXObject("Msxml2.XMLHTTP") } catch(e) {}
          try { return new ActiveXObject("Microsoft.XMLHTTP") } catch(e) {}
          return null;
        }
    function TestObject(user)
    {    this.m_user = user;    this.m_req = getXHR();
        if (!this.m_req)    throw "";    this.m_req.onreadystatechange = (function(that){return function()
        {alert(that.m_req.readyState);alert(that.m_user);
            if (that.m_req.readyState == 4)
            {
              var o = that.m_user;            alert(o + " done");        }
            that.m_req = null;
           that = null;
        }
        })(this);
    }TestObject.prototype.logIn = function()
    {    try {    var url;    url = "none.htm";//这里要改    this.m_req.open('GET', url, true);      this.m_req.send();
        } catch (ex) {    }}
        function main() {      var o1 = new TestObject("aaaaa");
          o1.logIn();
         var o2 = new TestObject("bbbbb");
          o2.logIn();
        }
    main() ;请LZ把url改成本域的某个html文件就好了,Ajax不能跨域取得内容
      

  6.   


    看来LZ原来是写java或者C++的吧JavaScript是一种解释型的脚本语言,所以当一个函数执行时,它的context是由执行时的环境决定的,像上例中的onreadystatechange函数,真正执行的时候,里面的作用域为全局window的作用域,所以this就为window对象。如果您要不认可这种3#和在下的这种编码方式,那也没办法了,这是由JavaScript得语言特性决定了,想要在JavaScript中使用面向对象的技术,使用闭包传递对象是必不可少的。
      

  7.   

    不好意思,写错了个地方function TestObject(user)
    {    this.m_user = user;    this.m_req = getXHR();
        if (!this.m_req)    throw "";
        var _this=this;  //这里用一个变量来代替this
        this.m_req.onreadystatechange = function()
        {
           //这里this.readyState在ie6是未定义,ie8居然可以,到该应该怎么写这里?
            if (this.readyState == 4)  //在这里还是用this
            {
                //还有这里,我想取得变量TestObject.m_user
                var o = _this.m_user;//这样写也不对,应该怎么写,
                         //↑这里就可以用_this来代替了
                alert(o.m_user + " done");
            }
        }
    }
      

  8.   


    说得没错,js中的this跟其它的this可完全不一样
      

  9.   

    function TestObject(user)
    {    this.m_user = user;
        var xhr=getXHR();
        this.m_req = xhr;

        if (!this.m_req)    throw "";    this.m_req.onreadystatechange = function()
        {
                      //这里this.readyState在ie6是未定义,ie8居然可以,到该应该怎么写这里?
            if (xhr.readyState == 4)
            {
                //还有这里,我想取得变量TestObject.m_user
                var o = this.m_user;//这样写也不对,应该怎么写,
                var o=user; //闭包么
                alert(o.m_user + " done");        }
        }
    }
      

  10.   

    谢谢各位,
    我就是用c++的思想来理解它, 可惨了那我该这么理解呢?   var _this=this;  //这里用一个变量来代替this      【这个不理解为临时变量那怎么理解啊?】
        this.m_req.onreadystatechange = function()……
    onreadystatechange 触发的时候上面那个_this像是全局变量一样?
    如果是全局变量那可不安全了,可能会有好多个TestObject实例同时在跑呢?
      

  11.   


    首先是这样的,LZ最好去找一些关于JavaScript作用域的教程看看,作用域对JavaScript很重要
    这里我就随便讲几点,可能不是很准确,请各位斧正。
    对于JavaScript来说,作用域可以说是以函数为范围的,而for, if 或者{}这些块里面是没有单独的作用域的一个函数就相当于一个作用域,下面代码做个简要解释function TestObject(user)
    {
    //#1
        this.m_user = user;    this.m_req = getXHR();
        if (!this.m_req)    throw "";    this.m_req.onreadystatechange = function()
        {//#2
             //todo
         //End #2
        }//End #1
    }
    var o1 = new TestObject("aaaaa");  //实例化,很重要因为o1对象通过new TestObject("aaaaa");语句实例化了,所以#1到#End#1之间适用的是o1这个实例的独立的作用域,而this.m_req.onreadystatechange 这个属性必须是一个函数,这里采用了匿名函数的写法,代码等价于function TestObject(user)
    {
    //#1
        this.m_user = user;    this.m_req = getXHR();
        if (!this.m_req)    throw "";    this.m_req.onreadystatechange = ToDo;
    //End #1
    }function ToDo()
    {//#2
        //Todo
     //End#2
    }
    var o1 = new TestObject("aaaaa");  //实例化,很重要所以在这个函数里的变量有自己的作用域既#2到End#2之间,而在#1到End#1之间的this就在这里获取不到了    var _this=this;  //这里用一个变量来代替this
        this.m_req.onreadystatechange = function()
        {
           //TODO(use _this)
        }以上的那种写法就是通过闭包把#1中的this"包"在了#2中,不过不用担心,这个不是全局变量,只有当系统运行到onreadystatechange函数中时候,_this变量才有意义,一旦对其没有引用了,JavaScript的GC回收机制就会将其回收
    以上,胡言乱语,欢迎指正!!!
      

  12.   

    你可以按照我给你的序号去理解就可以了,其实_this只是个局部变量,如楼上所说
    // 0)函数定义,直到定义结束,this都不会明确
    function TestObject(user)
    {// 2) this 开始产生,此时为 o1
        this.m_user = user;
        this.m_req = getXHR();
        if (!this.m_req)    throw "";
        
        // 8)当再次实例化时,_this此时为 o2
        var _this=this;  // 3) _this 产生,当然也是o1
        this.m_req.onreadystatechange = function() // 4)这算是一个函数的定义,此时函数并未运行,所以其中的this不明确
        {
           //这里this.readyState在ie6是未定义,ie8居然可以,到该应该怎么写这里?
             // 99)当某个时候onreadystatechange触发时,TestObject早已结束,所以this不是o1
             // 触发时,函数的运行者是m_req,所以this代表m_req,readyState是m_req.readyState
            if (this.readyState == 4)
            {
                //还有这里,我想取得变量TestObject.m_user
                //var o = this.m_user;//这样写也不对,应该怎么写,
                var o = _this.m_user;// 5)虽然是定义过程,但TestObject未结束,_this依然存在,此时是o1
                alert(o.m_user + " done");
            }
        }
         //6)TestObject运行结束,_this将消失,this也消失
    }
    var o1 = new TestObject("aaaaa"); // 1)实例化,TestObject也开始运行
    var o2 = new TestObject("bbbbb"); // 7)再次实例化,TestObject再次运行
      

  13.   

    LS说错了一个地方this.m_req.onreadystatechange = function() // 4)这算是一个函数的定义,此时函数并未运行,所以其中的this不明确
        {
           //这里this.readyState在ie6是未定义,ie8居然可以,到该应该怎么写这里?
             // 99)当某个时候onreadystatechange触发时,TestObject早已结束,所以this不是o1
             // !----- 触发时,函数的运行者是m_req,所以this代表m_req,readyState是m_req.readyState ------//
             //这里的this是window对象,onreadystatechange是运行在window既全局作用域下的,可以用来测试一下
             alert(this === window);//alert(true)
            if (this.readyState == 4)
            {
                //还有这里,我想取得变量TestObject.m_user
                //var o = this.m_user;//这样写也不对,应该怎么写,
                var o = _this.m_user;// 5)虽然是定义过程,但TestObject未结束,_this依然存在,此时是o1
                alert(o.m_user + " done");
            }
        }
      

  14.   

    呵呵,不好意思,IE是你说的那种情况
    FireFox是我说的那种情况问题考虑不周
      

  15.   


    原来FF是这种情况啊,还以为Ajax操作的方法除了创建,在所有浏览器下都一样,学到了
    P.S.这里this是window还是本身,W3C标准规定是哪个??
      

  16.   


    谢lq7和ice,我确实得找些作用域的教程看看,好像闭包的概念也很让我郁闷现在你们都说了_this是局部变量,// 0)函数定义,直到定义结束,this都不会明确
    function TestObject(user)
    {// 2) this 开始产生,此时为 o1
        this.m_user = user;
        this.m_req = getXHR();
        if (!this.m_req)    throw "";
        
        // 8)当再次实例化时,_this此时为 o2
        var _this=this;  // 3) _this 产生,当然也是o1
        this.m_req.onreadystatechange = function() // 4)这算是一个函数的定义,此时函数并未运行,所以其中的this不明确
        {
           //这里this.readyState在ie6是未定义,ie8居然可以,到该应该怎么写这里?
             // 99)当某个时候onreadystatechange触发时,TestObject早已结束,所以this不是o1
             // 触发时,函数的运行者是m_req,所以this代表m_req,readyState是m_req.readyState
            if (this.readyState == 4)
            {
                //还有这里,我想取得变量TestObject.m_user
                //var o = this.m_user;//这样写也不对,应该怎么写,
                var o = _this.m_user;// 5)虽然是定义过程,但TestObject未结束,_this依然存在,此时是o1
                alert(o.m_user + " done");
            }
        }
         //6)TestObject运行结束,_this将消失,this也消失
    }
    var o1 = new TestObject("aaaaa"); // 1)实例化,TestObject也开始运行
    var o2 = new TestObject("bbbbb"); // 7)再次实例化,TestObject再次运行
    TestObject运行结束,_this将消失,
    这里是说TestObject的构造函数而已吗?还是TestObject实例回收后,_this将消失,
    如果是函数返回后,_this将消失,   这onreadystatechange 还没触发呢,这个_this变量就被回收了,那触发的时候又怎么恢复的呢?看下面的顺序var o1 = new TestObject("aaaaa"); 
    var o2 = new TestObject("bbbbb"); o1.logIn ();
    o2.logIn ();
    两个异步请求都跑起来了,onreadystatechange触发的时候可能是o1的也可能是o2的对吧
    但是那个_this却有效,这javascript真神奇啊
      

  17.   

    在TestObject没结束之前
    this.m_req.onreadystatechange = function() {...} 这个赋值操作会把_this的值保存下来
    你可以认为 _this是C++中的一个指针