2

公開モジュール内に次のコードがありますが、imageListItem厳密に DTO であり、情報を隠す必要がない を宣言/定義する方法がわかりません。このオブジェクトを正しく定義していますか?

var imageListItem = function() {
    var _title;
    Object.defineProperty(this, "title", {
        get: function () { return _title; },
        set: function (value) { _title = value; }
        }
    );
};

var imageList = (function () {
    var buffer = new CBuffer();
    return {
        populate: function (listItems) {
            buffer.push(listItems);
        },
        rotate: function() {
             buffer.rotateLeft();
        }
    }
})();

ではimageListItem、後で使用するためにオブジェクト構造を宣言したいと考えています。その宣言は、そのオブジェクトが後でどのように使用されるかに論理的に依存するべきではありません。imageListItemつまり、新しいプロパティを動的に割り当てたり、誤ってプロパティを削除したりしたくありません。プロパティへの割り当ては、厳密には、オブジェクトで既に宣言されているプロパティに対してのみ行う必要があります。

Object.freeze()プロパティが追加または削除されないようにすることで、これをほぼ実現しますが、プロパティが変更されるのも防ぎます。

例えば、私はこれが欲しい:

var obj = {
  prop: function() {},
  foo: 'bar'
};

// New properties may be added, existing properties may be changed or removed
obj.foo = 'baz';
obj.lumpy = 'woof';

var o = Object.freeze(obj);

// Now any changes will fail
function fail(){
  'use strict';
  obj.delete(foo); // throws a TypeError
  obj.quaxxor = 'the friendly duck'; // throws a TypeError
}

私はこれをしたくない:

// Now any changes will fail
function fail(){
  'use strict';
  obj.foo = 'sparky'; // throws a TypeError
}

分かりますか?に追加されfreezeないようにしたいのですが、 の値を変更できないようにしたくありません。quaxxorobjfoo

4

1 に答える 1

5

あなたが探しているのは、 または のいずれObject.preventExtensions()Object.seal()です。

と同様にObject.freeze()、どちらのメソッドも新しいプロパティがオブジェクトに追加されないようにしますが、既存のプロパティの値を変更することは許可します

との違いはseal、データ アクセサーから/へのプロパティの削除と変換を厳密に禁止するpreventExtensionsことですが、実際には既存のプロパティの削除を妨げません。この動作は、使用している JS エンジンによって異なります (一部のエンジンでは、プロパティ、他のものはそうではないかもしれません)。sealpreventExtensions

基本的に、MDN ドキュメントから引用します。

このObject.preventExtensions()メソッドは、新しいプロパティがオブジェクトに追加されるのを防ぎます (つまり、オブジェクトへの将来の拡張を防ぎます)。[...]一般に、拡張不可能なオブジェクトのプロパティは引き続き削除される可能性があることに注意してください。

このObject.seal()メソッドはオブジェクトを封印し、新しいプロパティが追加されないようにし、既存のすべてのプロパティを構成不可としてマークします。現在のプロパティの値は、書き込み可能である限り変更できます。[...]シールされたオブジェクトのプロパティを削除または追加しようとしたり、データ プロパティをアクセサに変換したり、その逆を行ったりしようとすると、失敗します。

両方のメソッドの動作を示す例を次に示します。

var myFirstObj = { foo: 1 },
    mySecondObj = { bar: "baz" };

Object.preventExtensions(myFirstObj);
Object.seal(mySecondObj);

myFirstObj.foo = false; // Works fine
mySecondObj.baz = "hello"; // Works fine
delete myFirstObj.foo; // May work fine depending on your JS engine

(function() {
    'use strict';
    myFirstObj.qux = 'something'; // Throws a TypeError
    mySecondObj.qux = 'something'; // Throws a TypeError
    delete mySecondObj.foo; // Throws a TypeError
})();

さて、オブジェクトについてImageListItem言えば、コード行を追加するだけで目的を達成できます。

var ImageListItem = function() {
    var _title;
    Object.defineProperty(this, "title", {
        get: function () { return _title; },
        set: function (value) { _title = value; }
    });

    // Choose the one which fits your needs
    Object.preventExtensions(this);
    // or
    Object.seal(this);
};
于 2015-03-10T18:24:47.363 に答える