1

次のようなパターンを考えてみましょう。プロパティの getter/setter インターフェイスを定義して、内部検証を非表示にする必要があります。

var validThings = {
    'pretty name a': 3293293,
    'pretty name b': 8275850,
    'pretty name c': 2983855
};


function Constructor() {
    var internalThing = {
        name: 'pretty name a',
        id: '3293293'
    };

    Object.defineProperty(this, 'thing', {
        get: function() { return internalThing.name; },
        set: function(val) {
            var id = validThings[val];
            if (id) internalThing = { name: val, id: id };
        }
    });
}

これにより、ID について心配する必要がなくなり、次のように「もの」を設定できます。

var constructoid = new Constructor();
constructoid.thing = 'pretty name b';
constructoid.thing; // 'pretty name b';

そしてもちろん、無効な値に設定するのを防ぎます:

constructoid.thing = 'pretty name d';
constructoid.thing; // 'pretty name b';

しかし、オブジェクトの外部からも ID にアクセスできるようにしたいとしましょう。そのための最も自然なインターフェースは、モノのプロパティとしてです

constructoid.thing.id

しかし、「物」自体がゲッター/セッターである場合、そのようなプロパティを定義するにはどうすればよいでしょうか? 私は、関数、配列、アイスクリームコーンなど、JS で必要に応じて何でもプロパティをスローできることに慣れています。しかし、この場合、少なくとも私が考えることができた方法では不可能のようです。

Object.defineProperty(this.thing, 'id', {...}) // <-- error

もちろん、Constructor オブジェクト自体に「thingID」などのプロパティを単純に定義することも、モノの getter から名前と ID の両方を返すこともできます。私はそのような解決策を探しているわけではありませんが、明らかです。これは、定義されたプロパティでプロパティを定義することが実際に可能かどうかについての仮説的な質問です。

4

1 に答える 1

0

私は方法を発見しました:

    Object.defineProperty(this, 'thing', {
        get: function() {
            var name = internalThing.name;
            if (!name) return;
            name = new String(name);
            Object.defineProperty(name, 'id', {
                get: function() { return internalThing.id; }
            });
            return name;
        },
        set: function(val) {
            var id = validThings[val];
            if (id) internalThing = { name: val, id: id };
        }
    });

これまで String コンストラクターを使用する機会はありませんでしたが、特定の文字列にプロパティを追加できることがわかりました。誰かがより良いアプローチを持っている場合、私はまだこの効果を達成する他の方法に興味があります.


編集:

Felix Kling が指摘したように、コンストラクタとしての String は面倒です。上記のパターンは、最初の getter によって返された値がプリミティブでない場合、警告なしで機能するため、状況によっては役立つ可能性がありますが、プリミティブの場合、適切な解決策はないと思います。オブジェクトの要件は、値プロパティにも当てはまります。ただし、アクセサとは異なり、defineProperty は、以前に定義された値型のプロパティを最初の引数として受け入れます。おそらく、値プロパティは実際のオブジェクトと見なされますが、アクセサ プロパティは ... ファントムの抽象化ですか? それが何であれ、'it' が存在する (つまり、get 関数内) までは、物事を 'it' に固定することはできません。

于 2014-03-26T23:10:47.807 に答える