2012-11-27 46 views
0

我是新來的原型,我只是做了一個簡單的例子,不會工作。從下面的代碼顯而易見我想要的 - 一個計數器。但由於某種原因輸出始終爲5,我猜bind正在製作this對象的深層副本,然後綁定到該函數。有一個明顯的解決方案,我公開所有內容,但我想知道是否有更優雅的解決方案。 (或者你可以糾正我的錯誤,並告訴我沒有深層複製,但有一些其他錯誤)。 documentation沒有幫助我。Javascrtip綁定,它是否創建`this`的深層副本?

代碼:

<!DOCTYPE html> 
<html> 
    <body> 
     <input type="button" value="click" onclick="javascript: doTest();" /> 
     <div id="canvas"></div> 
     <script> 
      var ClassA = function (position, element) { // constructor 
       this.field1 = position; 
       this.target = element; 
      }; 

      ClassA.prototype = function() { 
       // private functions 
       var _aPrivateMethod = function(){ 
        console.log(this); 
        this.field1 += 1; 
        return this.field1; 
       }; 

       var _aPublicMethod = function(){ 
        this.target.innerHTML = _aPrivateMethod.bind(this)(); 
       }; 

       return { // interface 
        constructor: ClassA, 
        aPublicMethod : _aPublicMethod 
       }; 
      }(); 

      function doTest() { 
       var obj = new ClassA(4, document.getElementById('canvas')); 
       obj.aPublicMethod(); 
      } 
     </script> 
    </body> 
</html> 
+0

你在哪裏使用'.bind'? – pimvdb

+0

分配給'ClassA.prototype'的匿名函數從不使用(或獲取)其「self」參數。此外,您應該將立即調用的函數包裝在括號中以提高可讀性。 –

+0

對不起,在發佈我沒有清理之前嘗試的東西時,我犯了一些愚蠢的錯誤。謝謝你告訴我。 –

回答

1

這裏有一些問題。首先你每次打電話doTest。每次點擊都會創建一個新對象,因此無法增加field1

據我所知,你想要field1是私人的。在初始化它的方式,它不能是私人的。你可以這樣做:

function Person() { 
    var counter = 0; 
    this.increment = function() { 
     return ++counter; 
    } 
} 

這樣,你就無法從功能範圍之外訪問counter

另一個問題是您不要使用正確的上下文調用私有方法。如pimvdb所述,您應該使用_aPrivateMethod.call(this)

下面是一個例子:

function Person() { 

    var age = 0; 

    function incrementAge() { 
     return ++age; 
    } 

    function eatCake() { 
     console.log('Yey. I\'ll eat cake!'); 
    } 

    this.birthday = function() { 
     eatCake(); 
     return incrementAge(); 
    } 
} 

var p = new Person(); 
p.birthday(); //'Yey. I'll eat cake!', returns 1 
p.birthday(); //'Yey. I'll eat cake!', returns 2 

以這種方式eatCakeincrementAgeage是因爲功能範圍的所有私有。 這個例子中的壞事是我聲明函數birthday的方式。對於Person的每個實例,都將創建一個新副本。 正確的做法是:因爲我想用一個私有數據成員

Person.prototype.birthday = function() { ... } 

我的聲明是不喜歡這一個。其實不是私人只是本地的功能(ageeatCakeincrementAge)。 無法從原型中聲明的函數訪問它們,所以這就是爲什麼上面的例子中我選擇了這種方法。

+0

好吧,我必須等待接受你的回答,但謝謝。我錯過了每次啓動一個新對象的事實 - 現在工作正常! :) –

+0

太好了。我已經添加了一個繼承的例子。我希望這不是太複雜。如果有什麼不清楚的地方請讓我知道。 –

+0

謝謝,我明白了。對於你的(和將來的讀者)信息:在構造函數中聲明函數,使它們變成私有的,但是它們的副本將會爲每個實例創建。如果有很多人開始,這不太好。 –