¿Alguien tiene alguna implementación de ejemplo para hacer que los accesorios de objetos individuales sean de solo lectura / no configurables? Me refiero a los tipos de datos primitivos. Intenté usar ES5 Object API, pero choqué contra una pared de ladrillos.

No puedo mostrar el código, porque todavía está en esa fase "desordenada", pero básicamente estoy iterando a través de un objeto externo que, en sí mismo, contiene objetos numeruos. Esos objetos contienen cada uno varios tipos de datos primitivos. He hecho que los objetos externos sean de solo lectura, no configurados, etc., pero no puedo entender cómo hacer lo mismo para los accesorios individuales, los accesorios más internos.

Entonces, si outer.inner.prop === "Hello", quiero hacer ese valor readOnly.

¡Gracias!

ACTUALIZACIÓN

Acabo de descubrir esto, todo estaba en el ciclo for que estaba usando para iterar sobre los accesorios. Ahora tengo descriptores de datos para los accesorios, incluso los primitivos. :) ¡Gracias a todos!

2
Tom 18 jun. 2011 a las 16:57

4 respuestas

La mejor respuesta

Debe iterar a través del objeto interno, ya que no hay forma de congelar un objeto utilizando métodos estándar ES5.

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

Editar: También funciona para defineProperty si no quieres freeze:

function deepWriteProtect(obj) {
    Object.keys(obj).forEach(function (key) {
        if (typeof obj[key] == 'object')
            deepWriteProtect(obj[key]);
        Object.defineProperty(obj, key, { writable: false });
    });
}
2
user123444555621 18 jun. 2011 a las 13:17

¿Sería útil el siguiente ejemplo (ES5)? Crea un constructor vacío, con un captador para la propiedad a (y no establece, por lo que de facto a es de solo lectura):

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

No usar ES5 puedes hacer

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

Pero eso no es 100% seguro: Obj.prototype.getA puede sobrescribirse.

1
KooiInc 18 jun. 2011 a las 13:26

Aquí es un jsfiddle que muestra cómo puede usar las definiciones de get / setter ES5 para hacer que una propiedad de un objeto sea algo eso solo se puede obtener. El código se ve así:

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

Por supuesto, el captador podría obtener el valor de la propiedad ("x") desde cualquier lugar, como un cierre de un constructor o algo así. El punto es que el setter simplemente no cambia el valor, por lo que intenta cambiarlo:

object.x = 100;

No tendrá ningún efecto.

1
Pointy 18 jun. 2011 a las 13:52

No estoy 100% seguro de entender su pregunta correctamente, pero por lo que deduzco, está pidiendo variables privadas. Si es así, eso se puede lograr fácilmente utilizando cierres.

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
1
George Karpenkov 18 jun. 2011 a las 13:10