It is possible to create a immutable object in Javascript through the method Object.freeze
, and a immutable reference through the method Object.defineProperty
:
// Atribui a classe ao escopo global 'window'
Object.freeze(StaticTest);
Object.defineProperty(window, "StaticTest", {
value:StaticTest,
configurable:false,
writable:false
});
// Todas essas tentativas vão falhar silenciosamente:
// (ou lançar uma exceção, se o modo "strict" estiver ativado)
StaticTest = outroObjeto;
window.StaticTest = outroObjeto;
StaticTest.StaticAttribute = outroValor;
delete StaticTest.StaticAttribute;
As to prevent an object from being inherited, I don’t know any way of doing that, and I don’t think it’s possible at all.
Classical vs. Prototypical OO
Notice you asked about classes, but I gave my answer by just talking about objects. Why? Simply because, strictly speaking, Javascript does not have the concept of "classes".
In classical object orientation, used by the vast majority of languages that follow this paradigm, classes and objects (or instances) are distinct concepts: the class defines the "structure" and "behavior" of its objects, and each object belongs to a single class. Class inherits from class, so that instances of the specific class have similar structure and behavior to instances of the general class.
In the prototypical OO, there are only objects. An object defines its own structure and behavior, independently of the others. To reuse these features in other objects, they inherit directly of the existing object (here called prototype), modifying what you want and keeping (sharing) the rest. There are no classes, only construction functions.
Javascript heritage
For historical reasons, although conceptually Javascript is a language that follows the prototypical OO, its syntax attempts to "hide" the fact - making it more similar to the classical one. The result is a "salad", as shown below:
// Objeto simples: sem classe, sem construtor
var obj = {
atributo:"planeta",
metodo:function() {
return "Olá, " + this.atributo + "!";
}
}
// Construindo um objeto que herda de "obj"
function herdarDeObj() { }
herdarDeObj.prototype = obj;
var obj2 = new herdarDeObj();
alert(obj2.metodo()); // "Olá, planeta!"
obj2.atributo = "mundo";
alert(obj2.metodo()); // "Olá, mundo!"
alert( obj.isPrototypeOf(obj2) ); // true
alert( obj === Object.getPrototypeOf(obj2) ); // true
// Sintaxe confusa
alert( obj === obj2.prototype ); // false
alert( obj2.prototype ); // undefined
alert( obj === herdarDeObj.prototype ); // true
alert( obj === Object.getPrototypeOf(herdarDeObj) ); // false
alert( Object.getPrototypeOf(herdarDeObj) ); // function Empty() {}
// (varia conforme o browser)
alert( obj2 instanceof obj ); // false
alert( obj2 instanceof herdarDeObj ); // true
herdarDeObj.foo = "bar";
alert( obj2.foo ); // undefined
obj.foo = "baz";
alert( obj2.foo ); // "baz"
As you can see, we have two objects obj
and obj2
in which the second inherits from the first (or: the first is the prototype of the second). However, Javascript "hides" this simple relation, forcing us to create a constructor method, assign it the property prototype
and invoke it through the keyword new
.
But note that obj
is not prototype of herdarDeObj
- he is prototype of the built objects through the command new herdarDeObj()
. The constructor is a normal function, so much so that its prototype is the "empty function".
Probably due to this fact (from the constructor define everything about the object - both the initial attributes, placed in the constructor body through this.atr = val
, as for the prototype, the one from whom the object will inherit) people confuse it with the "class" of the object. And for the convenience that this constructor method offers, rarely does anyone use [explicitly] prototypic inheritance in practice, so much so that there are plans to introduce the concepts of classical OO in future versions of Javascript. Maybe someday, what you ask is actually possible.
Completion
Since there are no Javascript classes, it makes no sense to talk about "static classes" (not even "static attributes" or "class attributes"). If you want to expose a collection of attributes and methods using a given name, it is most natural to do so using a simple object:
window.StaticTest = {
StaticAttribute:"O atributo estático diz: Olá Planeta!",
StaticMethod:function() {
return "O método estático diz: Olá Mundo!";
}
};
You can make the object and reference immutable, as I explained, but you cannot prevent other objects from inheriting from it: anyone can create a new constructor function, assign StaticTest
as his prototype
and call this function - producing objects they inherit from StaticTest
.
+1 why is a good question! However, I will add an answer to define some concepts that are mixed in the question.
– utluiz