2011-04-16 64 views
0

給定一個實例變量,是否可以通過JavaScript訪問私有成員?例如,javascript封裝 - 任何訪問給定實例的私有成員的方式?

function class Foo() { 
    var x=12; 
    // some other stuff 
} 
F = new Foo(); 
// how to get/set F.x? 

更新:作爲一個轉折,假設該類有一個特權方法。是否有可能劫持該特權方法來訪問私人成員?

function class Foo() { 
    var x=12, y=0; 
    this.bar = function(){ y=y+1; } 
} 
F = new Foo(); 
// can I modify Foo.bar to access F.x? 
+0

純粹作爲_academic notion_您可以用'eval'來訪問本地關閉範圍注入的方法到真正的對象。我們不用真正的代碼來做這件事。沒有'F.x'如果你想'F.x'然後設置'this.x'。你可以效仿這樣的東西,但它可能會超過工程設計。 – Raynos 2011-04-16 00:41:39

+2

這不是事件有效的JavaScript代碼。沒有'class'關鍵字。 – 2011-04-16 01:46:02

回答

5

你需要一個privileged method得到的x /設定值:

function Foo() { 
    var x = 12; 
    this.getX = function() { return x; }; 
    this.setX = function(v) { x = v; }; 
} 

var f = new Foo(), 
    g = new Foo(); 

f.getX(); // returns 12 
g.getX(); // returns 12 

f.setX(24); 

f.getX(); // returns 12 
g.getX(); // returns 24 

g.setX(24); 

f.getX(); // returns 24 
g.getX(); // returns 24 

現場演示:http://jsfiddle.net/simevidas/j7VtF/

+0

我可以修飾類實例以動態添加特權方法嗎? – 2011-04-16 00:31:16

+0

@Andrew號一旦構造函數('Foo')創建了實例對象,'x'變量就會丟失 - 它在構造函數執行期間只存在**。 – 2011-04-16 00:33:01

+0

@AndrewB no。你不能。 – Raynos 2011-04-16 00:33:21

0

在您的例子中,變量x是本地一旦該函數超出範圍,構造函數及其值不會保留。但是,您可將值分配給對象的命名屬性,如:在JavaScript中被附着在物體

var Foo = function() { 
    this.x = 12; 
} 
var f = new Foo(); 
f.x; // => 12 
f.x = 123; // => 123 
0

私有成員,但他們不是在外部訪問,也不是訪問對象的自己的公共方法。他們可以通過私人方法訪問。私有方法是構造函數的內部函數。

你需要一個公共函數,它訪問最終訪問私有成員的私有內部函數。

編號:Better way to access private members in Javascript

+0

它們被附加到構造函數作用域而不是對象。 – Raynos 2011-04-16 00:34:59

3

你可以做這樣的事情,如果你真的這樣的訪問,但我真的不建議這樣做:

function Foo() { 
    var x = 12; 
    this.runContext = function(f) { 
      return eval(f); 
    }; 
} 

var f = new Foo(); 
f.runContext('alert(x);'); 
+0

**現場演示:** http://jsfiddle.net/simevidas/j7VtF/1/ – 2011-04-16 00:51:47

+0

'eval'是_devil_。 – Raynos 2011-04-16 00:59:32

+0

這就是爲什麼我***真***不推薦它:) – Ryan 2011-04-16 19:53:09

2

你可以寫你的代碼在一定的模式下實現這一點。

我會在underscore的幫助下演示來演示。

function Construct() { 
    this.foo = "foo"; 
    this._private = "bar"; 

    this.method = function() { 
     return 42; 
    }; 

    this._privateMethod = function() { 
     return "secret"; 
    }; 

    var that = this; 
    var inject = function(name, f) { 
     this[name] = _.bind(f, that); 
    }; 

    _.bindAll(this); 

    return { 
     "foo": this.foo, 
     "method": this.method, 
     "inject": inject 
    }; 
} 

var c = new Construct(); 
console.log(c.foo); // foo 
console.log(c.method()); // 42 
c.inject("foo", function() { 
    console.log(this._private); 
    console.log(this._privateMethod()); 
}); 
c.foo(); // bar, secret 

Live example

基本上在這裏你有兩個對象。您傳遞給客戶端的真實對象和代理對象。除了通過代理方法和變量之外,代理不能訪問真實狀態。

但它確實有一個注入方法,它允許您從代理