Есть ли способ предотвратить замену свойств объекта JavaScript? - PullRequest
12 голосов
/ 02 марта 2010

Я хотел бы сделать структуру объекта неизменной, предотвращая последующую замену его свойств. Однако свойства должны быть читабельными. Возможно ли это?

Я уверен, что нет языковых возможностей (по аналогии с final в Java и readonly в C #), чтобы поддержать это, но подумал, может ли быть другой механизм для достижения того же результата?

Я ищу что-то вроде этого:

var o = {
    a: "a",
    f: function () {
        return "b";
    }
};

var p = o.a;        // OK
o.a = "b";          // Error
var q = o.f();      // OK
o.f = function () { // Error
    return "c"; 
};

Ответы [ 6 ]

14 голосов
/ 02 марта 2010

ECMAScript 5 будет иметь seal() и freeze(), но нет хорошего способа сделать это с текущими реализациями JavaScript.

Источник .

9 голосов
/ 02 марта 2010

лучшее, что вы можете сделать, это спрятать свои свойства внутри замыкания.

var getMap = function(){
  var hidden = "1";
  return {
    getHidden : function() { return hidden; }
  }
}

var f = getMap ();

alert(f.getHidden());

Я нанес удар. В приведенном выше коде вам нужно будет не просто вернуть скрытый, но, возможно, скопировать его в новый объект. может быть, вы можете использовать JQuery Extension, чтобы сделать это для вас, поэтому вы будете возвращать новый объект, а не ссылку. Это может быть совершенно неправильно, хотя =)

5 голосов
/ 02 марта 2010

Использование var в конструкторе объекта создаст приватную переменную. Это по сути закрытие. Затем вы можете создать публичную функцию для доступа / изменения. Более подробная информация и примеры доступны на Private Member в Javascript от Douglas Crockford.

4 голосов
/ 07 марта 2012

Хорошо, уже было несколько ответов, предлагающих вернуть объект несколькими методами получения. Но вы все равно можете заменить эти методы.

Это немного лучше. Вы не сможете заменить свойства объекта без полной замены функции. Но это все еще не совсем то, что вы хотите.

function Sealed(obj) {
    function copy(o){
        var n = {}; 
        for(p in o){
            n[p] = o[p]
        }
        return n;
    }
    var priv = copy(obj);
    return function(p) {
        return typeof p == 'undefined' ? copy(priv) : priv[p];  // or maybe copy(priv[p])
    }
}

var mycar = new Sealed({make:"ford", model:"mustang", color:"black"});

alert( mycar('make') ); // "ford"
alert( mycar().make );  // "ford"

var newcopy = mycar();
newcopy.make = 'volkwagen';
alert( newcopy.make ); // "volkwagen"  :(

alert( mycar().make );   // still "ford"  :)
alert( mycar('make') );   // still "ford" :)
4 голосов
/ 02 марта 2010

Как сказал mkoryak, вы можете создать замыкание, чтобы скрыть свойства

function Car(make, model, color) {
    var _make = make, _model = model, _color = color; 

    this.getMake = function() {
        return _make;
    }

}

var mycar = new Car("ford", "mustang", "black");

mycar.getMake(); //returns "ford"
mycar._make; //error
2 голосов
/ 20 октября 2016

Теперь вы можете принудительно заморозить одно свойство объекта вместо того, чтобы заморозить весь объект. Вы можете достичь этого с помощью Object.defineProperty и параметра writable: false

var obj = {
    "first": 1,
    "second": 2,
    "third": 3
};
Object.defineProperty(obj, "first", {
    writable: false,
    value: 99
});

В этом примере значение obj.first теперь заблокировано на 99.

...