2013-07-08 67 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的范围(作为一个例子,我想打印它)。 每次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

错字..感谢您发现。 – 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