2016-06-22 8 views
3

このコードが私にエラーをもたらす理由はわかりません。私がしたいのは、配列をプロパティとして持つオブジェクトを作成することだけです。私はsetterとgetterでこれを実現したいが、何らかの理由で何らかの理由でthis.array = []内にsetArray関数がある最大呼び出しスタックサイズがを超えている。私は間違って何をしていますか? Javascriptのアクセサプロパティについては何が分かりませんか。Javascriptアクセサのプロパティの混乱

+0

*「...私はセッターとゲッターでこれを達成したい...」*あなたはゲッターが返すようにしたいですか?私は意図的に私の答えに1つを含めることから遠ざかっていました。なぜなら、配列を返すと、セットされたときには数字ですが、配列になると本当に奇妙なプロパティになります。それは普通理想的ではありません:-) –

答えて

4

あなたはそれが永遠に再帰的理由であるセッター、内からセッターとプロパティに代入している:、あなたが他の場所で値を格納する必要が

var obj = { 
    set array(size) {     // <== The property is called `array` 
     this.array = [];    // <== This calls the setter 
     for (var i = 0; i < size; i++){ 
      this.array[i] = i;   // <== This would fail because there's no getter 
     } 
    } 
}; 

ここで例えば、我々が作成プライベートスコープと変数の上に近い:

var obj = (function() { 
 
    var array = []; 
 
    return { 
 
     set array(size) { 
 
      array = [];    // No `this` here 
 
      for (var i = 0; i < size; i++) { 
 
       array[i] = i;   // No `this` here 
 
      } 
 
     }, 
 
     showArray() { 
 
      console.log(array); 
 
     } 
 
    }; 
 
})(); 
 
    
 
var myObj = Object.create(obj); 
 
myObj.array = 20; 
 
myObj.showArray();

あなたは機能の回避について尋ねました。プロパティの値を本当にプライベートにする関数が必要です。しかし、あなたが何らかの理由でそれを使用したくない場合、それが本当にプライベートであることに悩まされていない場合は、ZoltánTamásiが行ったことを行うことができますhis answer:同じオブジェクトに対して別のプロパティを使用します。彼の答えは基本的なプロパティ(例えば_array)に_という接頭語を使用しています。非常にというJavaScriptの共通規約では、プライベートプロパティはなくても「このままにしてください。事実、本当にプライベートプロパティを持つ言語(たとえば、インスタンスフィールドと呼ばれるJavaのようなもの)であっても、通常、それを回避するために使用できる強力なリフレクションメカニズムのいくつかの形式があります...

これを行うには、シリアライズする場合にJSONにそのプライベートプロパティを含めるかどうかを検討する必要があります。ない場合は、ちょうどあなたがコントロールすることができるようにどのプロパティがシリアル化中に含まれているだけでなくtoJSONを実装:

var obj = { 
 
    _array: [], 
 
    foo: "a value to include in JSON", 
 
    set array(size) { 
 
     this._array = [];   // Note the _ 
 
     for (var i = 0; i < size; i++) { 
 
      this._array[i] = i; 
 
     } 
 
    }, 
 
    showArray() { 
 
     console.log(this._array); 
 
    }, 
 
    toJSON() { 
 
     return { 
 
      // Here we list only the properties we want to have 
 
      // included in the JSON 
 
      foo: this.foo 
 
     }; 
 
    } 
 
}; 
 
    
 
var myObj = Object.create(obj); 
 
myObj.array = 20; 
 
myObj.showArray(); 
 
console.log(JSON.stringify(myObj));

+0

これは関数の呼び出しなしで可能ですか?だから、関数の結果と同じに設定せずにオブジェクトを作成できますか? –

+0

基本的な配列を適切に隠すため、つまりプライベートメンバーの可視性をシミュレートするには、関数クロージャが必要です。 –

+0

@ YasinYaqoobi:なぜそれをやっているのが問題なのですか?上記の真のプライベート変数を使用するには、関数が必要です。しかし、Zoltánのようにオブジェクトを別のプロパティとして配列を格納することもできます。その問題はどこのコードからでもアクセスできることです。どのくらいの問題があなた次第であるのか、多くの人がそれを心配することはありません。「_で始まり、それだけで大事にしてください。それを行うと、他のプロパティを列挙できないようにしたいので、JSONなどには表示されません。 –

2

this.array = []を書き込むときにセッター自体をセッター内部で使用しています。例えば_arrayと呼ばれる別のメンバーを紹介し、それをarrayプロパティの設定者に記入してください。

var obj = { 
    _array: [], 
    set array(size) { 
    for (var i = 0; i < size; i++){ 
     this._array[i] = i; 
    } 
    } 
}; 


var myObj = Object.create(obj); 
myObj.array = 20; 
+2

別のプロパティを使うと、ユーザが 'obj._array'にアクセスすることができるので、セッターを使う価値がいくらか無効になります。 @ T.J.Crowderのクロージャメソッドは、必要な場合に情報隠蔽を実装します。 – Barmar

+1

あなたは正しいです、私はちょうどコードのセマンティクスを扱わずに技術的な問題を指摘しました。ところで、私は今TypeScriptを何年も使用しています。そこには 'private'キーワードがあります(私のコーディング規則はプライベートメンバーの名前をアンダースコアで始めることです)。 –

0

あなたがセッターとゲッターを使用したいと述べていたが、このスニペットはちょうどOBJを使用しています。オブジェクトの配列を表示するにはshowArrayの代わりに配列を使用します。

var obj = (function() { 
 
    var _array = []; 
 
    return { 
 
     get array(){ 
 
      return _array; 
 
     }, 
 
     set array(size) { 
 
      _array = [];    
 
      for (var i = 0; i < size; i++) { 
 
       _array[i] = i;  
 
      } 
 
     } 
 
    }; 
 
})(); 
 

 
obj = Object.create(obj); 
 
obj.array = 20; 
 
console.log(obj.array);