2013-04-26 5 views
2
function MyClass() { 
    this.a = "me a"; 
    this.b = "me b"; 
}; 

MyClass.prototype.changeB = function(callback) { 
    this.a = "now me A"; 
    doAnotherFunction(function(err, data) { 
     this.b = "now me B"; 
    callback(null, this.b);}); 
}; 

function doAnotherFunction(callback) { 
    callback(null, null); 
}; 

main(); 

function main() { 
    var myclass = new MyClass(); 
    myclass.changeB(function(err, data) { 
    console.log("B: " + myclass.b + ", data: " + data);}); 
    console.log(JSON.stringify(myclass)); 
} 


When this runs: 
B: me b, data: now me B 
{"a":"now me A","b":"me b"} 

Пройдите меня легко, я новичок в javascript и размещаю здесь.node.js/javascript - вложенные обратные вызовы

Мой вопрос: почему 'this.b' не изменяется в оригинальном экземпляре MyClass? Я читал здесь, где javascript не имеет области блока (только область функций). Если это была причина, то почему бы ему не считать «this.b» «неопределенным», где он устанавливает «сейчас меня B»?

Спасибо!

+0

'this.b =" now me B "' находится внутри другой функции и вызывается в другом контексте выполнения. Поэтому 'this' не будет означать экземпляр' MyClass' в этом случае. –

ответ

2

Here is a good read для начала.

Для вашего конкретного примера, вы могли бы кодировать его, как это, сохраняя ссылку на this в MyClass Например:

MyClass.prototype.changeB = function(callback) { 
    var me = this; 
    this.a = "now me A"; 
    doAnotherFunction(function(err, data) { 
     me.b = "now me B"; 
     callback(null, me.b); 
    }); 
}; 

Пример использования bind в ответ на предложение:

MyClass.prototype.changeB = function(callback) { 
    this.a = "now me A"; 
    var fn = function(err, data) { 
     this.b = "now me B"; 
     callback(null, this.b); 
    }); 
    // the first parameter to bind will be the 'this' 
    // visible from inside the function 
    doAnotherFunction(fn.bind(this)); 
}; 

EDIT: Чтобы узнать, что this был в вашем примере, попробуйте добавить некоторые регистрации:

MyClass.prototype.changeB = function(callback) { 
    var me = this; 
    this.a = "now me A"; 
    doAnotherFunction(function(err, data) { 
     // Use this['b'] notation to avoid errors using this.b, 
     // if this.b doesn't already exist. 
     console.log(me, typeof me, this, typeof this, this['b']); 
     this.b = "now me B"; 
     callback(null, this.b); 
    }); 
}; 
+0

Я думаю, что это поможет объяснить причину, почему. – Jivings

+0

'bind' будет другим вариантом. – numbers1311407

+0

Спасибо за ссылку Paul. Я должен был добавить к своему первоначальному сообщению, что я действительно решил проблему, установив локальную переменную «me» в «this» (после того, как вы потянули много волосков :). Мое беспокойство заключается в том, почему не вложенная функция не указала фикцию «this.b» как «неопределенная»? Является ли это просто созданием нового объекта MyClass самостоятельно? – kevdev

2

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

Один из распространенных способов решить эту проблему, чтобы создать ссылку на this вы хотите получить доступ, вне обратного вызова:

var self = this; 

Затем вы можете ссылаться на self.b внутри обратного вызова.

+0

Спасибо, Нилс, я не могу пометить как ваши, так и ответы Павла как правильные. Как я уже говорил ниже, я считаю, что с каждым вызовом функции создается новый объект - я не понимаю причин этого. – kevdev

+0

хорошо, подумайте, используете ли вы обратный вызов в разных местах. Тогда что должно быть «этим»? – NilsH

+0

Обратный вызов находится внутри метода «changeB» MyClass, поэтому «это» обратного вызова должно быть «этим» из «changeB», которое должно быть «этим» из «myclass» (нижний регистр), которое было явно инстанцировано, один раз и только один раз, в «основном» методе. Думаю, не должно быть двух «это вообще». – kevdev

Смежные вопросы