2016-07-30 114 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