ES 5 introduziu algumas coisas muito legais em relação aos objetos
Uma coisa que muitas pessoas me dizem é “Javascript é legal e outras coisas, mas você não pode ter propriedades privadas ou protegidas em objetos, certo?”.
Esse é o ponto onde você gosta que eu fique longe de qualquer objeto pontiagudo.
Como alguns de vocês devem saber, as propriedades privadas são simples, se você seguir o padrão de módulo em Javascript:
var Cat = {};
Cat.create = function (config) {
var that = config || {name: "Kitty"};
var sound = "Meow";
that.says = function() { return sound; };
return that;
};
var myCat = Cat.create();
console.log(myCat.name + ": " + myCat.says()); // "Meow"
myCat.sound = "nyan";
console.log(myCat.name + ": " + myCat.says()); // still "Meow"
Portanto, neste exemplo, temos uma propriedade privada “sound” e você deve usar o getter para acessá-la.
Mas e as propriedades protegidas? O grande problema com a abordagem aqui é que não podemos realmente aproveitar a passagem da propriedade “sound” usando config, sem perder a proteção contra adulteração. Claro, existem soluções (por exemplo, especificação de parâmetros adicionais, etc.) – mas há uma maneira mais elegante:
ES5 é útil aqui com o adorável Object.defineProperty, que nos permite adicionar uma propriedade a um objeto com características especificadas, como ser somente leitura.
Portanto, uma versão estendida pode ter a seguinte aparência:
var Cat = {};
Cat.create = function (config) {
var that = config || {name: "Kitty"};
Object.defineProperty(that, "sound", {
value: (config && config.sound) || "Meow",
writable: false
});
that.says = function() { return this.sound; };
return that;
};
var myCat = Cat.create();
alert(myCat.name + ": " + myCat.says()); // "Meow"
myCat.sound = "nyan";
alert(myCat.name + ": " + myCat.says()); // still "Meow"
var nyanCat = Cat.create({name: "Nyan Cat", sound: "Nyan"});
alert(nyanCat.name + ": " + nyanCat.says()); // "Nyan"
nyanCat.sound = "Mew";
alert(nyanCat.name + ": " + nyanCat.says()); // still "Nyan"
Funky, não é?
Com isso, podemos facilmente entregar atributos que não queremos dar acesso de gravação ao público, mas ser capazes de ajustá-los de dentro da classe em que estamos.
Como herança pode ser tratada por meio do parâmetro “config” também, você tem algo como variáveis protegidas (apesar do fato de que ainda são visíveis ao público).