2013-07-08 2 views
2

У меня возникла проблема с кодом javascript.Область переменной в функции обратного вызова

У меня есть класс MyClass и добавлена ​​функция myFunction к ее прототипу.

MyClass.prototype.myFunction = function(file){ 
    if(some condition){ 
     fs.exists("./" + file, function(exists){ 
      if(exists) 
       console.log(this.someValue); 
       /* lot of other code */ 
      else 
       /* do something else */ 
    }); 
    }else{ 
     /* do something */ 
    } 
} 

Моя проблема заключается в область видимости this.someValue (в качестве примера я хочу просто напечатать его). Everytime exists равно true консольные журналы undefined, но это не так. Если бы я напечатал его за пределами fs.exists(), тогда он имеет значение, поэтому я предполагаю, что это проблема с определением области видимости.

Как я могу получить доступ к this.someValue в этом примере?

Заранее благодарен!

ответ

2

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

MyClass.prototype.myFunction = function(file) { 
    if(some condition) { 
    var self = this; // create variable with pointer to 'this' 
    fs.exists("./" + file, function(exists) { 
     if(exists) { 
     console.log(self.someValue); // we can access it to parent scope variables 
     /* lot of other code */ 
     } else { 
     /* do something else */ 
     } 
    }); 
    } else { 
    /* do something */ 
    } 
} 

Как проверить эту гениальную тему: How does the "this" keyword work?

+1

'{location: London" 'недействителен, fwiw – naomik

+0

Typo .. Спасибо за то, что вы заметили. – moka

3
MyClass.prototype.myFunction = function(file){ 
    var that = this; 
    // some lines of code later... 
     console.log(that.someValue); 
} 
4

Вы должны .bind ваша внутренняя функция

MyClass.prototype.myFunction = function(file){ 
    if(some condition){ 
     fs.exists("./" + file, function(exists){ 
      if(exists) 
       console.log(this.someValue); 
       /* lot of other code */ 
      else 
       /* do something else */ 
    }.bind(this)); 
    }else{ 
     /* do something */ 
    } 
} 

Это может быть переписано, чтобы быть чисты

MyClass.prototype.myFunction = function myFunction(file){ 
    if(some condition){ 
    fs.exists("./" + file, this.doSomething.bind(this)); 
    } 
    else{ 
    // do something else 
    } 
} 

MyClass.prototype.doSomething = function doSomething(exists) { 
    if(exists) { 
    console.log(this.someValue); 
    // lot of other code 
    } 
    else { 
    // do something else 
    } 
} 

Я лично нравится это решение, потому что это позволяет поддерживать отличный код композицию и предотвращает вас от гнездования function(){ function(){ function(){ ... }}}. Это также мешает вам иметь кучу var that = this; или var self = this; переменных, плавающих вокруг, если вы задаетесь вопросом, какая область это.

.bind медленнее, да, но, как отмечает minitech, это, безусловно, не будет вашим узким местом по сравнению с доступом к файлу.

+0

Связывание является одним из самых медленных способов прохождения указателя области видимости в другую функцию. И имеет несколько другое назначение. – moka

+1

@MaksimsMihejevs: Медленно относительно доступа к файлу? Не микро-оптимизировать ... – Ryan

+1

Не относится к работе с файлами, но медленнее для такой простой работы. На самом деле это драматическая разница, пожалуйста, посмотрите здесь: http://jsperf.com/bind-vs-closure-setup/6 – moka

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