2015-06-30 62 views
1

另一个JavaScript范围问题。我相信这与'提升'无关。启用模块模式的Javascript范围问题

我在这里已经一个很小的代码块 - http://jsfiddle.net/0oqLzsec/2/

var c = function(){ 
    var x = 'before', 
     callBefore = function(){ 
      alert(x); 
     }, 
     callAfter = function(){ 
      _callAfter(); 
     }; 

    return{ 
     callBefore : callBefore, 
     callAfter : callAfter 
    } 

    var y = 'after'; 

    function _callAfter(){ 
     alert(y); 
    } 
}; 

var obj = c(); 
obj.callBefore(); 
obj.callAfter(); 

callAfter()总是提醒“未定义”即使变量y _callAfter()之前定义。但如果我在变量x之前移动变量y声明,它正在工作。

我想知道如果callAfter()可以_callAfter()它定义如下,为什么不能读取变量y?

+1

这是一个提升的问题。变量y声明被挂起,但不是赋值。 –

+1

“**还有一个** JavaScript范围问题”?你的问题可能会也可能不会每次都被同一个人看到,所以这有点不合适...... –

+1

很简单,你在声明'y'之前返回,所以它是未定义的... – dandavis

回答

2

它关系到吊装,var y移到函数的顶部,但分配(y = 'after')不是,所以它永远不会运行,因为它是return statement后。

JS引擎重写你的代码看起来是这样的:

var c = function(){   
    // functions also get hoisted to the top 
    function _callAfter(){ 
     alert(y); 
    } 
    var x = 'before', 
     callBefore = function(){ 
      alert(x); 
     }, 
     callAfter = function(){ 
      _callAfter(); 
     }, 
     // y declaration is hoisted to the top of the function 
     y; 

    return { 
     callBefore : callBefore, 
     callAfter : callAfter 
    }; 

    // the assignment never gets called because it's after the return 
    y = 'after'; 
}; 
3

_callAftery都被挂起,这使得它们通过函数调用被称为局部变量。函数_callAfter能够被调用(和你一样),并且它也关闭变量y。但是,在从c函数返回之前,此变量未获得赋值的值。因此,你得到undefined。如果您在返回之前放置var y;,并且在返回之后放入y='after';也是如此。

换句话说,下面的两个是等效的:

function foo(){ 
 
    var a; 
 
    return function(){ return a }; 
 
    a = 42; // never runs 
 
} 
 
alert(foo()()); 
 

 
function bar(){ 
 
    return function(){ return a }; 
 
    var a = 42; 
 
} 
 
alert(bar()());

下面是示出局部变量被悬挂的示例,并且关闭了,即使当文字的功能的var之前发生代码:

function build() { 
 
    return function(newValue) { 
 
    alert("was: " + oldValue); 
 
    oldValue = newValue; 
 
    alert("now: " + oldValue); 
 
    } 
 
    var oldValue = 42; 
 
} 
 

 
f = build(); 
 
f(17); 
 
// was: undefined 
 
// now: 17 
 

 
f(99); 
 
// was: 17 
 
// now: 99