Подтвердить что ты не робот

Есть ли способ предотвратить замену свойств объекта JavaScript?

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

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

Я ищу что-то в этих строках:

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"; 
};
4b9b3361

Ответ 1

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

Источник.

Ответ 2

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

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

var f = getMap ();

alert(f.getHidden());

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

Ответ 3

Использование var в конструкторе объекта создаст приватную переменную. Это, по сути, закрытие. Затем вы можете создать публичную функцию для доступа/изменения. Дополнительная информация и примеры на Частные члены в Javascript Дугласа Крокфорда.

Ответ 4

Как сказал 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

Ответ 5

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

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

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" :)

Ответ 6

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

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

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