2012-05-23 95 views
13

我有這個類:JavaScript的私有函數訪問公共變量

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    } 
} 

,並稱之爲:

var myobj = new ctest(); 
    myobj.func1(); 

是不應該的是,第二次警報會彈出「忽忽」? func2是私有的,它不能訪問var1公共變量嗎?

如果一個私有函數不能訪問一個公共變量,我該怎麼做呢?

在此先感謝!

+2

另外,這裏沒有像'private'這樣的東西。 – Alexander

+0

這個'obj.func1()'大概應該是'myobj.func1()' – forsvarir

+0

@forsvarir是的它應該 - 我爲他修復了它。 – Alnitak

回答

17

您需要提供呼叫上下文來func2

this.func1 = function() { 
    alert(this.var1); 
    func2.call(this); 
    alert(this.var1); 
} 

沒有上下文的通話將使用全局對象(即window) - 你應該看到當您運行當前的代碼,window.var1是在兩個警報之間創建。

+0

如果我按照你的建議說它說func2()不是函數 – MIrrorMirror

+0

@MIrrorMirror啊,恩,是 - 堅持! – Alnitak

+0

@Alnitak請閱讀他的代碼,func2不是公共職能。 – xdazz

0
function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(this); 
     alert(this.var1); 
    } 
    var func2 = function(obj) { 
     obj.var1 = "huhu"; 
    } 
} 

而且還有其他的方式來解決這個問題,檢查其他答案:)

+0

downvoter應該給你的理由。 – xdazz

+0

@Alnitak但這不會成爲問題,'obj'是參數。 – xdazz

12

功能不依賴於實例,因此您的func2調用最終成爲不調用指向this與預期實例。

您可以修復的調用,包括上下文:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2.call(this); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    } 
} 

或者你可以保持一個變量通緝對象引用各地:

function ctest() { 
    var that = this; 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     that.var1 = "huhu"; 
    } 
} 
+0

謝謝!這對我有很大的幫助 –

+0

您能提供關於此主題的進一步閱讀,因爲我想知道哪些是最佳做法,爲什麼 – InsOp

+1

@InsOp我建議閱讀關於「this」關鍵字的MDN幫助:https://developer.mozilla。org/en-US/docs/Web/JavaScript/Reference/Operators/this – Lucero

2

另一種選擇是使用Function.bind

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    }.bind(this); 
} 

請注意,瀏覽器對此的支持並不完美。

+0

爲什麼要同時使用'that' _and_'.bind()'? – Alnitak

+0

@Alnitak:可憐的複製和粘貼 – Eric

2

在JS中沒有私人的東西,但是您可以使用closures與示波器一起玩。

比方說,在你的例子中,你不需要公開var1作爲公共財產。你可以很容易地重寫代碼爲如下:

function ctest() { 
    var var1 = "haha"; 

    this.func1 = function() { 
     alert(var1); 
     func2(); 
     alert(var1); 
    } 

    var func2 = function() { 
     var1 = "huhu"; 
    } 
} 

因爲無論func1func2股範圍相同 - 他們是在同一個函數定義,ctest - 他們可以訪問相同的變量。當然在這種情況下,您沒有var1暴露,所以:myobj.var1undefined

如果你想var1暴露財產,那麼你需要的是bindfunc2你在構造函數創建的對象實例:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var func2 = function() { 
     this.var1 = "huhu"; 
    }.bind(this); 
} 

否則func2將有不同的上下文對象(this)。如果瀏覽器不支持bind,你不想使用墊片(如上面的鏈接),你可以再次採取封閉的優勢:

function ctest() { 
    this.var1 = "haha"; 
    this.func1 = function() { 
     alert(this.var1); 
     func2(); 
     alert(this.var1); 
    } 
    var context = this; 
    var func2 = function() { 
     context.var1 = "huhu"; 
    } 
} 

IMVHO是那麼優雅。