2016-07-30 117 views
0

为什么会发生以下情况?访问JS中的外部函数范围时发生问题

function f1() { 
    this.myRefVar = 30; 
    this.myRefVar2 = 30; 
    var parent = this; 

    return function() { 
     this.myRefVar = 20; 
     console.log('parent contains ' + Object.keys(parent).filter(function(k) { 
      return k.indexOf('myRefVar') > -1; 
     })); 
     console.log('parent value of myRefVar: ' + parent.myRefVar); 
     console.log('this value of myRefVar: ' + this.myRefVar); 
    }; 
} 

f1()(); 

输出:

parent contains myRefVar,myRefVar2 
parent value of myRefVar: 20 
this value of myRefVar: 20 
+1

只需在'f1'中加''use strict';'看看会发生什么。 – ftor

+0

我想我现在明白了,在一个函数内使用'this'(而不是''constructor' now object'method')与定义一个不使用'var'的变量相同,这是一件坏事,因为这会使变量请参阅全局范围,而不是函数本地范围。 –

回答

2

因为实际上这里没有作用域。所有this访问都是指window对象。因此,当您在内部范围编辑this.myRefVar时,实际上您正在编辑window处的值。

var theName = "SO"; 
var myObject = function(){ 
    this.theName = "SO2"; 
    this.foo = function() { 
     this.theName = "SO3"; 
    } 
} 

在这里,我定义了一些变量和函数。变量theName,首先在root(window)范围中声明,那里面myObject范围(目前是这样的没有范围,只是为了说明,然后里面foo范围。)

console.log(theName); // SO 
console.log(this.theName); // SO 
console.log(window.theName); // SO 
console.log(myObject.theName); // undefined 
console.log(myObject.foo); // undefined 
console.log(this.foo); // undefined 
console.log(window.foo); // undefined 

在这里,我试图通过不同的方式访问theName变量。如果实际上在这里进行搜索,则第4个函数应该在函数调用后工作。其他人只代表相同的想法,但方式不同。

myObject(); 

console.log(theName); // SO2 
console.log(this.theName); // SO2 
console.log(window.theName); // SO2 
console.log(myObject.theName); // undefined 
console.log(myObject.foo); // undefined 
console.log(this.foo); // function myObject/this.foo() 
console.log(window.foo); // function myObject/this.foo() 

函数调用后,我仍然无法访问myObject.theName为我所希望的。那是因为,这样调用myObject.theName实际上并没有访问myObject范围,而不是我试图访问theName属性的myObject函数。而且,如果没有实际定义/实例化/创建此功能作为对象,我无法访问属性。

myObject.theName;// undefined. Accessing myObject as a function 
new myObject().theName // SO2. Accessing an object derived from myObject. 

这是怎么回事在你的代码实际上是不scopping而关闭。为了更好地理解:
Scopping
Closures
Similar SO question

+0

我喜欢你的答案,但是我无法理解你所提供的所有例子。 –

+0

Aha,现在清除。 –

1

在JavaScript函数具有全局范围 例如

function parent() { 
    var self_parent = this; 
    function firstChild() { 
    var self_first_child = this; 
    function childOfChild() { 
     var self_child_of_child = this; 
    } 
    } 
} 

在下面,上面的代码将是真正的

self_parent === self_first_child === self_child_of_child 

更多信息见JavaScript-Garden-About-this