プッシュ、カウントが必要です。すべての配列メソッド/アクセサー/イテレーターが必要になる場合があります。さらに、コレクションを配列にすると、速度が向上します。
したがって、最善の解決策は、配列から継承し、オブジェクトを実際の配列にすることです。オブジェクトには何も定義せず、すべてをプロトタイプに定義する必要があります。
-->> 配列の速度とすべての機能を無料で利用できます。
関数は次のようになります。
function MsgObjCollection() { /* nothing */ };
var SO_pr = ( MsgObjCollection.prototype = [] ) ;
次に、プロトタイプで送受信されるカウントを定義するには、 Object.defineProperty を使用して列挙を汚染しないようにし、getter/setter も含めます。
Object.defineProperty(SO_pr, 'sent', { get : function() {
var cnt = 0;
this.forEach( function(x) { if (x.source == 'Sent') cnt++; });
return cnt; } } );
Object.defineProperty(SO_pr, 'received', { get : function() {
var cnt = 0;
this.forEach( function(x) { if (x.source == 'Received') cnt++; });
return cnt; } } );
Object.defineProperty(SO_pr, 'count', { get : function() { return this.length } ,
set : function (x) { this.length = x } });
Msg コレクションのプロトタイプは新しい配列であるため、MsgObjCollection のプロトタイプを変更するときに配列のプロトタイプを汚染しないことに注意してください。
必要な Sent および Received プロパティはより複雑です。これらは、基になるオブジェクトのビューとして機能します。
できることの 1 つは、元の配列の適切な項目から構築された新しい配列を返すようにすることです。
ただし、元の配列の周りにラッパーを構築して、1) このビューを介して変更できるようにし、2) ガベージの作成を回避することを好みます。
フィドルはここにあります:http://jsfiddle.net/cjQFj/1/
Object.defineProperty(SO_pr, 'Sent',
{ get : function() { return getWrapper('Sent', this); } } ) ;
Object.defineProperty(SO_pr, 'Received',
{ get : function() { return getWrapper('Received', this); } } ) ;
function getWrapper(wrappedProp, wrappedThis) {
var indx = 0, wp=null;
// try to find a cached wrapper
while (wp = getWrapper.wrappers[indx++] ) {
if (wp.wthis === this && wp.wprop==wrappedProp) return wp.wrapper;
};
// no wrapper : now build, store, then return a new one
var newWrapper = {
get count() { return (wrappedProp=='Sent') ? wrappedThis.sent : wrappedThis.received },
unshift : function () { if (this.count == 0) return null;
var indx=0;
while (wrappedThis[indx].source != wrappedProp ) indx++;
var popped = wrappedThis[indx];
while (indx<wrappedThis.length-1) {wrappedThis[indx]=wrappedThis[indx+1]; indx++; }
wrappedThis.length--;
return popped;
}
};
getWrapper.wrappers.push({ wthis : wrappedThis, wprop : wrappedProp, wrapper : newWrapper });
return newWrapper;
};
getWrapper.wrappers = [];
ちょっとしたテスト:
var myColl = new MsgObjCollection();
myColl.push({ source : 'Sent', message : 'hello to Jhon' });
myColl.push({ source : 'Received' , message : 'hi from Kate' });
myColl.push({ source : 'Sent', message : 'hello to Kate' });
myColl.push({ source : 'Received' , message : 'Reply from Jhon' });
myColl.push({ source : 'Received' , message : 'Ho, i forgot from Jhon' });
console.log('total number of messages : ' + myColl.count);
console.log('sent : ' + myColl.sent + ' Sent.count ' + myColl.Sent.count);
console.log('received : ' + myColl.received + ' Received.count ' + myColl.Received.count);
console.log('removing oldest sent message ');
var myLastSent = myColl.Sent.unshift();
console.log ('oldest sent message content : ' + myLastSent.message);
console.log('total number of messages : ' + myColl.count);
console.log('sent : ' + myColl.sent + ' Sent.count ' + myColl.Sent.count);
console.log('received : ' + myColl.received + ' Received.count ' + myColl.Received.count);
出力 : >>
total number of messages : 5
sent : 2 Sent.count 2
received : 3 Received.count 3
removing oldest sent message
oldest sent message content : hello to Jhon
total number of messages : 4
sent : 1 Sent.count 1
received : 3 Received.count 3
厄介な部分は、これらのビュー プロパティが配列ではないことですが、[] 演算子をオーバーロードできないため、元の配列で完全に透過的なビューを作成することはできません (つまり、myBox.Sent[i] は正確に i 番目になります)。送信されたメッセージ) したがって、ある時点で、いくつかの操作のためにその場で配列を作成したい場合があります。