Ответ 1
ECMAScript 5 будет иметь seal()
и freeze()
, но нет хорошего способа сделать это с помощью текущих реализаций 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";
};
ECMAScript 5 будет иметь seal()
и freeze()
, но нет хорошего способа сделать это с помощью текущих реализаций JavaScript.
лучшее, что вы можете сделать, это скрыть ваши свойства внутри закрытия.
var getMap = function(){
var hidden = "1";
return {
getHidden : function() { return hidden; }
}
}
var f = getMap ();
alert(f.getHidden());
Я принял удар. В приведенном выше коде вам нужно будет не просто вернуть скрытый, но, возможно, скопировать его в новый объект. возможно, вы можете использовать jquery extend, чтобы сделать это для вас, поэтому вы будете возвращать новый объект, а не ссылку. Это может быть совершенно неверно, хотя =)
Использование var
в конструкторе объекта создаст приватную переменную. Это, по сути, закрытие. Затем вы можете создать публичную функцию для доступа/изменения. Дополнительная информация и примеры на Частные члены в Javascript Дугласа Крокфорда.
Как сказал 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
Хорошо, так что уже есть несколько ответов, в которых предлагается вернуть объект с несколькими методами 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" :)
Теперь вы можете принудительно заморозить одно свойство объекта, а не замораживать весь объект. Вы можете достичь этого с помощью Object.defineProperty
и параметра writable: false
var obj = {
"first": 1,
"second": 2,
"third": 3
};
Object.defineProperty(obj, "first", {
writable: false,
value: 99
});
В этом примере obj.first
теперь имеет значение, заблокированное до 99.