【问题标题】:JavaScript "is not a function" error when calling defined method调用定义的方法时 JavaScript“不是函数”错误
【发布时间】:2013-03-27 18:57:05
【问题描述】:

这是我的代码:

request_xml: function()
        {
        http_request = false;
                    http_request = new XMLHttpRequest();
                     if (http_request.overrideMimeType) 
                            {
                            http_request.overrideMimeType('text/xml');
                            }
                          if (!http_request)
                          {
                                return false;
                          }
                        http_request.onreadystatechange = this.response_xml;
                        http_request.open('GET', realXmlUrl, true);
                        http_request.send(null);
                        xmlDoc = http_request.responseXML;

},



response_xml:function ()
    {
        if (http_request.readyState == 4)
        {
            if(http_request.status == 404 && countXmlUrl<=3)
            {
                countXmlUrl++;

                realXmlUrl = xmlUrl[countXmlUrl];
                this.request_xml();
            }
            if (http_request.status == 200)
            {
                xmlDoc = http_request.responseXML;
                alert("need to update3");
                this.peter_save_data();
            }

        }
    },

peter_save_data:function()
    {
// removed function code
},

奇怪的是,警报触发没有问题,但下面的函数调用给了我这个错误:

Error: this.peter_save_data is not a function

从别处的另一个函数调用同一个该死的函数可以正常工作。

【问题讨论】:

  • 我想这是因为您在错误的范围内使用了this。您是否尝试过将其传递给 peter_save_data() 函数但像 objWhatever.peter_save_data(this) 一样调用它?
  • 这不是完整的代码。缺少的一个重要难题是如何 response_xml 被调用——这很重要,因为它将改变this 是什么(参见Jared 的评论)。请记住,this 可以被认为是“方法调用的接收者”。
  • 为什么不用它的限定名来称呼它?
  • @anirudh4444 想象一下上面的代码来自prototype 声明。因此,这是可以使用的最通用的形式。
  • 好的,为了清楚起见编辑了帖子...我粘贴完整代码没有问题,但它是一个大文件...

标签: javascript javascript-events


【解决方案1】:

您可以在调用 XML 生成之前执行此操作。

var that = this;

以后……

that.peter_save_data();

因为this在使用新函数改变作用域时经常改变,你不能使用它访问原始值。将其别名为 that 允许您仍然访问 this 的原始值。

【讨论】:

  • 我认为这是一个潜在的不必要的全局变量,它可能难以调试(例如,如果它已经被其他东西使用或在其他地方设置并且在方法完成时没有清除)。
  • 该变量不需要是全局的。它需要在本地声明,仅在上下文更改之前。
  • 非常感谢这解决了我的问题!
【解决方案2】:

缺少的一个重要难题是如何response_xml 被调用。这很重要,因为它会改变 this 是什么(参见 Jared 的评论)。

请记住,this 可以被认为是(大致)“方法调用的接收者”。如果将response_xml 直接传递给用作回调,那么它当然不起作用——this 很可能是window

考虑这些:

var x = {f: function () { return this }}
var g = x.f
x.f() === x    // true
g() === x      // false
g() === window // true

编码愉快。


“修复”可能只是改变response_xml 的调用方式。有很多方法可以做到这一点(通常使用闭包)。

例子:

// Use a closure to keep he object upon which to explicitly invoke the method
// inside response_xml "this" will be "that",
// which was "this" of the current scope
http_request.onreadystatechange = (function (that) {
   return function () { return that.response_xml() }
}(this)

// Or, alternatively,
// capture the current "this" as a closed-over variable...
// (assumes this is in a function: var in global context does not create a lexical)
var self = this
http_request.onreadystatechange = function () {
   // ...and invoke the method upon it
   return self.response_xml()
}

就个人而言,我只会使用 jQuery 或类似的 ;-)

【讨论】:

  • @Ryan 更新了修复答案 ;-)
  • 我对你的评论投了赞成票,但对于像我这样的新手来说,这有点难以理解。虽然这两种解决方案都有效,但我正在使用下面的一个(在我的脑海中更简单),所以我接受了那个作为答案。希望你不介意,希望我能在这里选择两个答案,谢谢!
  • @Ryan 没关系 :-) 希望我的示例对您有所帮助,并且您的问题得到解决。重要的是要记住 JavaScript 中的方法没有绑定到一个对象——它们只是普通的函数! this 仅通过调用它们的方式正确传播。 (可以使用callapply 更改或更改“接收器”,如图所示)。
【解决方案3】:

如果您想要类似类的行为,请使用正确的语法,使用该语法的库正在使用 JSON 将参数传递给生成类的函数。

function MyClass(CTOR paarams){
    var response_xml=function ()
    {
        if (http_request.readyState == 4)
        {
            if(http_request.status == 404 && countXmlUrl<=3)
            {
                countXmlUrl++;

                realXmlUrl = xmlUrl[countXmlUrl];
                this.request_xml();
            }
            if (http_request.status == 200)
            {
                xmlDoc = http_request.responseXML;
                alert("need to update3");
                this.peter_save_data();
            }

        }
    }

    var peter_save_data=function()
    {
       // removed function code
    }
}

var Test = new MyClass(somthing,another_something);
Test.response_xml();
//etc etc.

或者,使用 Mootools 之类的库,您可以将其作为 JSON 进行:

var T = new Class({
    response_xml:function ()
    {
        if (http_request.readyState == 4)
        {
            if(http_request.status == 404 && countXmlUrl<=3)
            {
                countXmlUrl++;

                realXmlUrl = xmlUrl[countXmlUrl];
                this.request_xml();
            }
            if (http_request.status == 200)
            {
                xmlDoc = http_request.responseXML;
                alert("need to update3");
                this.peter_save_data();
            }

        }
    },

    peter_save_data:function()
    {
      // removed function code
    }

});
var X = new T();//etc etc

【讨论】:

    猜你喜欢
    • 2020-11-07
    • 2015-02-24
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 2021-12-17
    相关资源
    最近更新 更多