Javascript类在函数内调用函数

时间:2012-06-04 07:53:43

标签: javascript prototypejs

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 个答案:

答案 0 :(得分: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));

答案 1 :(得分:0)

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

解决方案: 将其缓存在本地变量中。

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] );
        }
    });
};

答案 2 :(得分:0)

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

$.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] );
    }
});

答案 3 :(得分: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或具有垫片的浏览器(如上面描述的链接所示)。

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

谈论闭包:你不需要在构造函数中声明函数。通过这种方式,它们会一直动态添加,如果它们无法访问某些内部变量,则没有理由,这只是浪费资源。为了清楚起见,在你的情况下,如果你有:

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()