2

私はずっと前から、ネイティブ配列と通常のオブジェクトの間の境界線を完全に曖昧にして、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"

このアプローチは私にとって非常に興味深いものです。しかし、それはまた、いくつかの深刻な問題に苦しんでいるようです!

  1. 元のmyObjモデルをいくつかの新しいプロパティで拡張してみませんか?extendAsArrayプロパティに関する更新を行うために、すべてのプロパティ変更を実行する必要がlengthありますか?

  2. プロパティが変更された場合、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やアンダースコアについても言及しないでください。私は両方のタイプのメソッドの包括的なカスタムリストを持っており、おそらくシムなしの標準で完成した標準を使用するつもりであり、それをリファクタリングするつもりはありません!

4

2 に答える 2

1

これがあなたの質問だと思います:

プロパティが変更、追加、または削除されたときに、オブジェクトの配列インデックスとその長さプロパティをどのように更新しますか?

それを行うためのメソッドを作成するので、基本的にObjectの内部メソッドを模倣します。ゲッターやセッターではできないと思いますが、間違っているかもしれません。

残りは答えというよりはコメントです。

私はずっと前に、ネイティブ配列と通常のオブジェクトの間の境界線を完全に曖昧にすることをいとわなかった

線はすでに完全にぼやけています。配列はオブジェクトであり、それらを際立たせる唯一のものは、それらの特別な長さのプロパティです。

EcmaScript 5は、一般的な方法を導入することで、この傾向を先取りしたようです。

ES5はジェネリックメソッドを導入していません。少なくともed3以降はその言語で使用されています。

1つのタイプで定義されますが、どのタイプでも使用できます

まったくそうではありませんが、実際にはES5の方が制限が厳しくなります。ed 3では、callを使用してthisArgをオブジェクトにapply強制するか、何も渡されなかった場合はグローバルオブジェクトに置き換えます。thisArgを変更せずに渡すES5ではそうではありません。Object(*thisArg*)

配列をオブジェクトとして使用する際の制限は、言語自体ではなく、規則に関連しています。ほとんどの開発者は、オブジェクトまたは配列を使用する必要がある場合に明確な違いがあることを認識しています。オブジェクトのような配列を実際に使用する必要がある場合はほとんどありませんが、それらが存在することは間違いありません。jQueryは、オブジェクトが配列プロパティを利用する例です。たとえば、セレクターによって収集された要素は数値プロパティとして追加され、要素の数である長さプロパティがあります。このようにして、ジェネリック配列メソッドをjQueryオブジェクトに適用できます(ちなみに、すべてed 3にあります)。

このObject.watchメソッドはJavaScrpit™にあり、ES5の一部ではないため、注意して使用してください。

組み込みオブジェクトの独自のバージョンを作成する際の主な問題は、おそらくすべての組み込みメソッドをネイティブメソッドでラップし(jQueryがすべてのDOMメソッドをほぼラップするように)、すべてのプロパティでゲッターとセッターの設定を開始することです。 、またはプロパティアクセスを置き換える関数呼び出し(jQueryvalやメソッドなど)attrで終わります。propかなり退屈で、パフォーマンスが重要な場合は遅くなります。

申し訳ありませんが、jQueryについて言及しました…:-(

言語がうまく機能しない、またはネイティブに機能しないことを強制しようとするよりも、言語が持つ機能を最大限に活用するようにライブラリまたはフレームワークを設計する方が賢明なようです。

しかし、試してみて満点。:-)

于 2013-03-13T00:07:44.397 に答える
0

ライブラリwatch.jsがあり、プロパティの更新または新しいプロパティの追加も監視しています。 試してみる!

setIntervalで動作するため、パフォーマンスには適していません。

ハーモニーが出ているとき、私たちは簡単に次のことを行うことができます。

Object.observe(obj,Observer);

そのための仕様を確認してください: ハーモニー

ただし、後でオブジェクト拡張にフォーカスがない場合は、初期化時にオブジェクト全体をフリーズできます。プロパティの変更やプロパティの追加に煩わされることはありません。

それに応じてコードが変更されます。

extendAsArray = function z_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', {
        value:index
       });
       if(!Object.freeze){
          Object.defineProperty(Object, "freeze", {
                enumerable: false
              , configurable: false
              , writable: false
              , value: function (obj) {
                  var props = Object.getOwnPropertyNames(obj);
                  for(var i=0; i<props.length; i++){
                      var desc = Object.getOwnPropertyDescriptor(obj,props[i]);
                      if("value" in desc ){
                         desc.writable = false;
                      }
                      desc.configurable = false;
                      Object.defineProperty( obj, props[i], desc );
                  }
                  return Object.preventExtensions(obj);
              }
          });
       }
       Object.freeze(obj);
    }
    return obj;
};

また、前回の投稿で言及されたアンガス・クロルがそれについて話していることを知りました。

「はい、underscore.jsのようなよく書かれたライブラリによって提供される同等の機能を利用できますが、それでもメソッドが静的でオブジェクトが単なる追加の引数である非標準の反転署名にロックされています。インスタンスのみの言語。ある時点で、サポートされているすべてのブラウザーはES5に準拠します。その時点で、シムされたコードベースはシムライブラリを削除して続行できますが、シムされていないブラウザーは、主要なリファクターまたは永続的に非標準のいずれかを選択する必要があります。静的ユーティリティライブラリ。」

于 2013-03-13T02:45:44.867 に答える