私はずっと前から、ネイティブ配列と通常のオブジェクトの間の境界線を完全に曖昧にして、ES5で取得した配列と同じ機能でオブジェクトを拡張するだけでなく、両側のメソッドのカスタムパッケージとバンドルすることを望んでいました。
賢い人々のカップルは、これらのパラダイムの変化について考えました。アンガス・クロルが記事javascript-object-keys-finallyで言及したように:
「さらに、配列と通常のオブジェクトの間の境界線が曖昧になると(カスタムゲッターとセッターによって支援されます)、非数値識別子とアクセスの両方の長所を享受する一般的な「配列のような」オブジェクトの成長が見られる可能性があります。 Array.prototypeによって定義された豊富なAPIセット。EcmaScript5は、1つのタイプで定義されているが、どのタイプでも使用できるジェネリックメソッドを導入することで、この傾向を先取りしたようです。」
途中で、彼は記事にコード化されたものを取得します: extending-objects-with-javascript-getters
function extendAsArray(obj) {
if (obj.length === undefined || obj.__lookupGetter__('length')) {
var index = 0;
for (var prop in obj) {
if(!obj.__lookupGetter__(prop)) {
(function(thisIndex, thisProp) {
obj.__defineGetter__(thisIndex, function() {return obj[thisProp]});
})(index, prop)
index++;
}
};
obj.__defineGetter__("length", function() {return index});
}
return obj;
}
var myObj = {
left:50,
top:20,
width:10,
height:10
}
extendAsArray(myObj);
[].map.call(myObj,function(s){return s+' px'}).join(', ');
//"50px ,20px ,10px, 10px"
このアプローチは私にとって非常に興味深いものです。しかし、それはまた、いくつかの深刻な問題に苦しんでいるようです!
元のmyObjモデルをいくつかの新しいプロパティで拡張してみませんか?
extendAsArray
プロパティに関する更新を行うために、すべてのプロパティ変更を実行する必要がlength
ありますか?プロパティが変更された場合、
length
関連するのはプロパティだけではありません。配列のようなプロパティ要求は間違いなく未定義であることが判明するため、配列インデックスも更新する必要があります。そうするときconsole.log(myObj.length) -> 4 myObj.zAxis=0
それから
console.log(myObj[4]) // -> undefined! console.log(myObj.length) // -> 4!
それに応じてAngusのコードを変更したので、length
リクエストに応じてプロパティの自動更新をサポートします。
function extendAsArray(obj) {
var index = 0;
for(var prop in obj){
if(!obj.__lookupGetter__(prop)){
(function(thisIndex, thisProp){
Object.defineProperty(obj, thisIndex, {
get: function(){return obj[thisProp]}
, enumerable: true
, configurable: true
, writeable: true
});
})(index, prop)
index++;
}
}
if(!obj.__lookupGetter__('length')){
Object.defineProperty(obj, 'length', {
get: function(){
return extendAsArray(obj);
}
, configurable: true
, writeable: true
});
return obj;
}
else{
return index;
}
}
length
問題は、プロパティが変更、追加、または削除されたときに、オブジェクトの配列インデックスをそのプロパティと一緒に更新するにはどうすればよいかということです。
使用する必要がありますObject.watch
か?
そして、まだ解決されていない質問があります。一貫した方法でオブジェクトに対してもそれを作成した、私自身のシミングされていないユーティリティライブラリに干渉する方法は?
私は両方のタイプに同じコードベースを使用しています:z.Object({}).mapEvery
同じことをしますz.Object([]).mapEvery
JQueryやアンダースコアについても言及しないでください。私は両方のタイプのメソッドの包括的なカスタムリストを持っており、おそらくシムなしの標準で完成した標準を使用するつもりであり、それをリファクタリングするつもりはありません!