Javascript - Свойство класса экземпляра не определено после обратного вызова из $ .post - PullRequest
1 голос
/ 21 ноября 2011

У меня есть следующий фрагмент js:

<script language="javascript">
          function test() {
            this.a = 10;
        };
        test.prototype.next = function () {
            alert('before: ' + this.a);
            $.ajax({
                url: 'some-url',
                async: true,
                type: 'POST',
                dataType: 'json',
                success: this.callback

            });
        };
        test.prototype.callback = function () {
            alert('after: ' + this.a);
        };

        $(document).ready(function () {
            var test1 = new test();
            test1.next();
        });
      </script>

Это всегда дает результат: before: 10 after: undefine.

Почему в функции обратного вызова $ .post, свойства классане определены.Кто-нибудь может мне помочь?Большое спасибо.

Ответы [ 5 ]

7 голосов
/ 21 ноября 2011
success: this.callback

Это не сработает.Вам необходимо привязать обратный вызов к экземпляру (this).В противном случае он потеряет свой размах.Одна функция, к сожалению, не запомнит ее.

Ручной способ будет

var me = this;

// .....

success: function(x,y,z) { me.callback(x,y,z) }

, и я не могу найти встроенный помощник, который есть у jQuery для этого сейчас.В CoffeeScript вы просто используете жирную стрелку =>.

Обновление: нашел способ jQuery: есть параметр context, который можно указать для $.ajax, иэто станет this для всех обратных вызовов:

 success:  this.callback,
 context:  this
1 голос
/ 21 ноября 2011

Вы теряете контекст, поэтому this указывает на другой объект. В jQuery есть встроенная прокси-функция. Измените свой код следующим образом:

// ...
$.ajax({
    url: 'some-url',
    async: true,
    type: 'POST',
    dataType: 'json',
    success: $.proxy(this.callback, this)
});
// ...
0 голосов
/ 21 ноября 2011

несколько изменений в вашем коде, как показано ниже,

<script language="javascript">
          function test() {
            this.a = 10;
        };
        test.prototype.next = function () {
            alert('before: ' + this.a);
            var oThis = this;          //Save refernce of Test() function in a varaiable. then use it 
            $.ajax({
                url: 'some-url',
                async: true,
                type: 'POST',
                dataType: 'json',
                success: oThis.callback // This is change this=> earlier was referring 
                                        //$.ajax object so save this of test() 
                                        // in a variable and then use it 
            });
        };
        test.prototype.callback = function () {
            alert('after: ' + this.a);
        };

        $(document).ready(function () {
            var test1 = new test();
            test1.next();
        });
      </script>
0 голосов
/ 21 ноября 2011

Другой способ сделать это - сделать обратный вызов локальной функцией, которая имеет доступ к локальной области и сохранить ссылку на this в локальной области.Я думаю, что это может работать нормально, потому что обратному вызову может потребоваться доступ к this, но это не обязательно должен быть метод для этого.

    test.prototype.next = function () {
        var self = this;

        function callback() {
            alert('after: ' + self.a);
        }

        alert('before: ' + this.a);
        $.ajax({
            url: 'some-url',
            async: true,
            type: 'POST',
            dataType: 'json',
            success: callback

        });
    };
0 голосов
/ 21 ноября 2011

Проблема связана с закрытием функции.«this» для обратного вызова не указывает на «test», а на саму функцию обратного вызова.

Используйте что-то вроде этого

function binder (func, thisValue) {
            return function () {
                return func.apply(thisValue, arguments);
            }
        }

var bindedFun = binder(function () {
            alert('after: ' + this.a);
        }, test);
...