2011-12-25 36 views
11

有沒有辦法從模塊模式動態訪問私有變量的公共功能? 測試1顯示了我的意思與「動態訪問」,但與公共變量是否可以動態訪問模塊模式中的私有變量?

var x = (function(){ 
    var x=0, y=2, z=5; 

    return { 
     toast: 123, 
     test1: function(arg){ 
      return this[arg]; 
     }, 
     test2: function(){ 
      // ?? 
     } 
    }; 
}()); 

console.log(x.test1("toast")); // 123 
console.log(x.test2("y")); // should return 2 

我結束了創建一個私有變量(一個對象)存儲我的私有變量,所以我能夠訪問他們這樣

privateVarStore[privateVarName] 

但有沒有另一種解決方案呢?

回答

9

DEMO

是。

抱歉,讓亞當Rackis但你可以(在邪惡)EVAL做到這一點:

var x = (function(){ 
    var x=0, y=2, z=5; 

    return { 
     toast: 123, 
     test1: function(arg){ 
      return this[arg]; 
     }, 
     test2: function(a){ 
      return eval(a) 
     } 
    }; 
}()); 

console.log(x.test1("toast")); // 123 
console.log(x.test2("y")); // should return 2 -> does return 2 

這是那些少數的例外情況eval應使用一個。

編輯,按照漢斯乙PUFAL建議(意見),你可以而且應該驗證參數test2如下:

test2: function(a){ 
    return /^[$_a-z][$_a-z0-9]*$/i.test (a) ? eval(a) : undefined; 
} 
+3

爲了避免安全問題,建議添加一個驗證,即參數到test2確實是一個簡單的變量:return/^ [$ _ a-z] [$ _ a-z0-9] * $/i.test(a)? eval(a):undefined; – HBP 2011-12-25 05:56:27

+0

@HansBPUFAL:好主意!我一定會把它加上 – qwertymk 2011-12-25 06:10:17

+1

+1,但是我能否提出另一種驗證思路:如果你定義了一個列出哪些私有變量可以通過公共函數訪問的對象,比如'var accessList = {「x」 :true,「y」:true};'然後在'function test2(a)'你可以說'return accessList [a]? eval(a):undefined; - 優點是這不僅提供了可以傳遞給eval的字符串的安全性,還允許你定義其他真正的私有變量,這些變量不能通過'test2() 。 – nnnnnn 2011-12-25 11:55:30

7

(至少不是沒有訴諸eval,每qwertymk的答案)。

y不是x屬性(考慮命名此對象的東西比x更好地避免與局部變量x混亂)。 y是一個局部變量,其中x的方法已經形成閉包。

任何x的方法可以訪問y,但不應該說this.y,而是通過直接訪問y

再次,y是不是你的對象的財產x。它只是創建了x的函數中的局部變量,因此導致x的方法在其上形成閉包。

因此,要test2返回y,只是做:

test2: function(){ 
    return y; 
} 

要創建一個方法可以讓你訪問私有變量,可以考慮這樣的事情:

var x = (function() { 
    var privateMembers = { x: 0, y: 2, z: 5 }; 

    return { 
     getPrivate: function (name) { 
      return privateMembers[name]; 
     }, 
     toast: 123, 
     test1: function (arg) { 
      return this[arg]; 
     }, 
     test2: function() { 
      // ?? 
     } 
    }; 
})(); 

而且那麼

alert(x.getPrivate("y")); //alerts 2 

退房this fiddle

+0

你會怎麼推薦蒂姆解決缺少代碼'TEST2()' ? – mauris 2011-12-25 04:31:37

+0

偉大的答案,但那是我的替代解決方案(創建一個單獨的私人對象,以訪問我的私有變量在公共職能),我想知道是否有另一種(更美麗)的方式來做到這一點? – 2011-12-25 04:43:37

+0

@Tim--不是我能想到的。就個人而言,我認爲上面的方式更美觀:) – 2011-12-25 04:45:17

相關問題