Создание примитивных типов данных readOnly / nonConfig в JavaScript - PullRequest
2 голосов
/ 18 июня 2011

Есть ли у кого-нибудь примерная реализация того, чтобы отдельные объекты поддерживали readOnly / не конфигурируемые?Я имею в виду примитивные типы данных.Я пытался использовать ES5 Object API, но столкнулся с кирпичной стеной.

Я не могу показать код, потому что он все еще находится в этой «грязной» фазе, но в основном я перебираю внешний объект, который сам по себе,содержит множество объектов.Каждый из этих объектов содержит различные примитивные типы данных.Я сделал внешние объекты readOnly, неконфигурированными и т. Д., Но не могу понять, как сделать это для отдельных реквизитов, для самых внутренних реквизитов.

Итак, если outer.inner.prop === "Hello", я хочу сделать этозначение readOnly.

Спасибо!

ОБНОВЛЕНИЕ

Я только что понял, все это было в цикле for, который я использовал для итерацииболее реквизита.Теперь я на самом деле получил дескрипторы данных для реквизита, даже примитивных.:) Спасибо всем!

Ответы [ 4 ]

2 голосов
/ 18 июня 2011

Вы должны выполнить итерацию по внутреннему объекту, поскольку нет способа глубокой заморозки объекта с использованием стандартных методов ES5.

function deepFreeze(obj) {
    Object.keys(obj).forEach(function (key) {
        if (typeof obj[key] == 'object')
            deepFreeze(obj[key]);
    });
    Object.freeze(obj);
}

Edit: Также работает для defineProperty, если вы не хотите freeze:

function deepWriteProtect(obj) {
    Object.keys(obj).forEach(function (key) {
        if (typeof obj[key] == 'object')
            deepWriteProtect(obj[key]);
        Object.defineProperty(obj, key, { writable: false });
    });
}
1 голос
/ 18 июня 2011

Здесь - это jsfiddle, показывающий, как вы можете использовать определения получателя / установщика ES5, чтобы сделать свойство объекта чем-то, что может быть только извлечено.Код выглядит следующим образом:

var object = {
    get x() {
        return 17;
    }, set x() {
        alert("You cannot set x!");
    }
};

Конечно, получатель может получить значение свойства ("x") из любого места, например, замыкание из конструктора или что-то еще.Дело в том, что установщик просто не меняет значение, поэтому пытается изменить его:

object.x = 100;

не будет иметь никакого эффекта.

1 голос
/ 18 июня 2011

Поможет ли следующий (ES5) пример?Он создает пустой конструктор с геттером для свойства a (и без сеттера, так что де-факто a только для чтения):

var Obj = function(){};
Obj.prototype = {
    get a() {return 5;}
}
var x = new Obj;
alert(x.a); //=> 5
x.a = 6; //=> TypeError: setting a property that has only a getter

Не используя ES5, вы можете сделать

var Obj = function(){
  var a = 5;
  if (!Obj.prototype.getA) {
     Obj.prototype.getA = {
         toString: function() {
            return a;
         }
     };
  }
}

var y = new Obj;
alert(y.getA); //=> 5

Но это не на 100% безопасно: Obj.prototype.getA может быть перезаписано.

1 голос
/ 18 июня 2011

Я не уверен на 100%, что правильно понял ваш вопрос, но из того, что я понял, вы спрашиваете о личных переменных. Если это так, это может быть легко достигнуто с помощью замыканий.

function myClass(){
    var mySecretProperty = 10;
    this.getMySecretProperty = function(){
         return mySecretProperty;
    }
    this.changeMySecretProperty = function(s){
         // whatever logic you need for a setter method
         mySecretProperty = s;
    }
}

var myObj = new MyClass();
myObj.changeMySecretProperty(120);
myObj.getMySecretProperty(); // will return 120
myObj.mySecretProperty // will return undefined
...