0
function ObjectProvider() {
    this.url = "ajax/inbounds.php"
    this.inBounds = function () {
        this.removeMarkers();
        var url_string = this.url;
        $.getJSON(url_string, function (data) {
            for (i = 0; i != data.length; ++i) {
                this.createObject(data[i]);
            }
        });
    };
    this.createObject = function (_data) {};
    this.removeMarkers = function () {};
};

所以这条线

this.createObject( data[i] );

有一些问题,但是

this.removeMarkers();

工作正常。

这两个函数都在 ObjectProvider 对象中定义。尝试添加一个名为 test() 的函数,只是不喜欢在 JSON 回调函数中调用任何内容。

4

4 回答 4

4

这是一个典型的范围界定问题;this里面你的回调$.getJSON()函数已经不一样了this

this要解决问题,您必须在调用之前保留参考$.getJSON(),例如

var self = this;
$.getJSON(url_string, function(data) {
    // self.createObject( data[i] );
});

或者,使用以下方法绑定成功回调函数$.proxy

$.getJSON(url_string, $.proxy(function(data) {
    this.createObject(data[i]);
}, this));
于 2012-06-04T07:57:56.527 回答
1

thisajax 回调中的 位于不同的上下文中。

解决方案:将其缓存在局部变量中。

this.inBounds = function(){
    var self = this;
    self.removeMarkers();
    var url_string = this.url;
    $.getJSON(url_string, function(data) {
        for( i=0; i != data.length; ++i ){
            self.createObject( data[i] );
        }
    });
};
于 2012-06-04T07:57:28.830 回答
0

问题是,您将一个函数传递给 getJSON,该函数将被调用,“this”指向全局对象或 jQuery 定义的某个自定义对象。如果您希望回调中的“this”指向您的对象,请使用 bind 方法(在某些较旧的浏览器中不可用,但您可以轻松找到模拟此方法的项目)。

$.getJSON(url_string, function(data) {
    for( i=0; i != data.length; ++i ){
        this.createObject( data[i] );
    }
}.bind(this));

或定义一个辅助变量,该变量将指向此回调外部的“this”并在内部使用该变量。

var self = this;

$.getJSON(url_string, function(data) {
    for( i=0; i != data.length; ++i ){
        self.createObject( data[i] );
    }
});
于 2012-06-04T07:58:20.700 回答
0

我不喜欢getJSON这个原因,与ajax.

基本上,当success函数执行时,this不再指向您的ObjectProvider实例。为了解决这个问题,您可以改用ajax,它提供了一个有用的context属性:

function ObjectProvider(){
  this.url = "ajax/inbounds.php"
  this.inBounds = function(){
    this.removeMarkers();

    var url_string = this.url;
    $.ajax({
      url: this.url,
      dataType: "json",
      context: this,
      success: function(data) {
        for( i=0; i != data.length; ++i ){
            this.createObject( data[i] );
        }
    });
  };

  this.createObject = function(_data){};
  this.removeMarkers = function(){};
};

否则你可以使用bind

$.getJSON(url_string, function(data) {
    for( i=0; i != data.length; ++i ){
        this.createObject( data[i] );
    }
}.bind(this));

为了创建一个“绑定”到特定上下文对象的新函数,但仅限于支持 ES5 或具有 shim 的浏览器(如上面的链接所述)。

还有提到的版本,用于存储实例的闭包,但我个人更喜欢避免在不是绝对必要的情况下。如今,对于这种行为,它被认为是一种古老的做法。

谈论闭包:你不需要在构造函数中声明函数。这样,它们一直是动态添加的,如果它们没有访问某些内部变量,那就没有理由了,这只是浪费资源。需要明确的是,在您的情况下,如果您有:

var a = new ObjectProvider();
var b = new ObjectProvider();

console.log(a.createObject === b.createObject) // false

更好的方法可能是:

function ObjectProvider() {
}

ObjectProvider.prototype = {
    constructor: ObjectProvider,

    url: "ajax/inbounds.php",

    inBounds: function () { /* ... */ },
    createObject: function () { /* ... */ },
    removeMarkers: function () { /* ... */ }         
}

var a = new ObjectProvider();
var b = new ObjectProvider();

console.log(a.createObject === b.createObject) // true

但是此时,如果您没有任何动态属性(例如,URL 始终相同,不作为参数传递给构造函数)也许您也不需要拥有不同的实例,并且您可以刚刚开始:

var ObjectProvider = {
    url: "ajax/inbounds.php",

    inBounds: function () { /* ... */ },
    createObject: function () { /* ... */ },
    removeMarkers: function () { /* ... */ }         
};

并将其用作“单例”:

ObjectProvider.createObject()
于 2012-06-04T08:57:41.960 回答