2009-03-23 6 views
2

JSの可変スコープが私を邪魔しています。次のコードでは、setClientパブリックメソッドを使用してclientIDを設定すると、getClientメソッドを使用してtrackメソッド内から値にアクセスできます。しかし私はprivateメンバー 'version'の値にこの方法(または他のプライベートメンバー)の値にアクセスすることはできません。私はvar _this = thisはContainer関数のスコープへのアクセスを許可する何らかのソートのクロージャを作成すると仮定しました。JS可変スコープ

今、私は混乱しています。私はこれがおそらく本当に簡単だと分かっているので、私はここで尋ねると思った。地球上のどこでスティックの間違った端を把握していますか?

function Container() 
{ 
    // private members 
    var version = '0.1'; 
    var CID = false; 
    var _this = this; 

    // public members 
    this.getVersion = function() { return _this.version; } 
    this.getClient = function() { return _this.CID; } 
    this.setClient = function(CID) { _this.CID = CID; } 

    // private methods 
    this.getQS = function() { return _this.version; } 

    // public methods 
    this.track = function() 
    { 
     if (_this.CID) 
     { 
      var date = new Date(); 

      data = 
      { 
       cid: _this.getClient(), 
       sw: screen.width ? screen.width : false, 
       sh: screen.height ? screen.height : false, 
       d: date.getTime() 
      } 

      qs = ''; 

      for (p in data) { qs += p+'~'+data[p]+'-'; } 

      var elHd = document.getElementsByTagName("head")[0];   
      var elScr = document.createElement('script'); 

      elScr.type = 'text/javascript'; 
      elScr.src = 'http://example.org/'+qs+ 
          'version-'+_this.getVersion(); 

      elHd.appendChild(elScr); 
     } 
     else 
     { 
      alert('no client ID'); 
     } 
    } 
} 

答えて

1

コンテナのコンストラクタをクリアしてください。 バージョンとCID変数はプライベートでコンテナコンストラクタのスコープ内にあるため、このスコープ参照は不要で、全く動作しません。この。パブリックアクセス可能なプロパティとメソッドには参照が必要で、第2のコードブロックに示すように、プロトタイプをコンストラクタ関数の外部で定義する場合は非常に便利です。

function Container() { 
    var version = "0.1", CID = false; 

    this.getVersion = function()  { return version }; 
    this.getClient = function()  { return CID  }; 
    this.setClient = function(value) { CID = value }; 

    this.track = function() { 
    if (CID) { 
     var qs = "", data = { 
     cid: this.getClient(), 
     sw: screen.width ? screen.width: false, 
     sh: screen.height ? screen.height: false, 
     d: (new Date).getTime() 
     }; 
     for (var p in data) qs += p +"~"+ data[p] +"-"; 
     var js = document.createElement("script"); 
     js.type = "text/javascript"; 
     js.src = "http://example.org/"+ qs +"version-"+ this.getVersion(); 
     document.getElementsByTagName("head")[0].appendChild(js); 
    } else { 
     alert("No Client ID"); 
    } 
    }; 
}; 

これです。コンストラクタの後にプロトタイプを追加/オーバーライドしているときは、リファレンスが重要になります。 JavaScript関数は、バージョンを参照クロージャあるので

function Container2() { } 
Container2.prototype = { 
    CID: null, 
    version: "0.1", 
    track: function() { 
    alert(this.version); 
    } 
} 
+0

ありがとうございます。私は、私が何らかの種類のクロージャーまたはバックリファレンスを作成する必要があるという誤った印象の下で明確に働いていました。私はそれが私のためのo'reillyの本に戻っていると思う – jthompson

+0

問題はない、それの周りにあなたの頭を包むために少しかかる。 そして、ここの別の記事で述べたように、http://www.crockford.com/javascript/private.htmlは、どのように動作するかを固めるのを助ける素晴らしい読書です。 –

0

は、私はあなたが混乱しているところ、私は理解してるかわからない(あるいは、なぜあなたは、物事にあなたが道をやっているので、私は、メタ混乱する場合があります)。

this.getVersion = function() { return version; } 
0

変数バージョンは、Containerクラスのメンバフィールドではありません:あなただけ行う場合はどうなります。これはコンテナコンストラクタの間のみ存在するローカル変数です。あなたは(あなたが方法であるとして)ので、それを作成する必要があります。

this.version = "0.1"; 

あなたはCIDフィールドのために同じことを行う必要があります。まだ、クラスのプロトタイプオブジェクトにそれらを追加してください。

0

単純な答えは

this.getVersion = function() { return version; } 

を使用することで、上記の関数内のローカル変数は、偶関復帰後にアクセスすることができます。 _this.versionにアクセスしようとすると、バージョン_thisオブジェクトを読み取ろうとしています。 _thisバージョンメンバーを割り当てたことがないため、値は未定義です。

JavaScriptで

、あなただけ明示的にあなたが作業しているオブジェクトに追加、またはそのオブジェクトのプロトタイプ、またはプロトタイプのプロトタイプに追加されたメンバーにアクセスできるようになります、など

詳細情報JavaScriptを使用したプライベートメンバーの使用については、Douglas Crockfordの素晴らしい記事に記載されています。Private Members in JavaScript