3 ms·
While in principle, Javascript's object system is prototypal, in practice you can use it as if it were class-based; in fact, before the addition of Object.creat
by cygx 15y ago
While in principle, Javascript's object system is prototypal, in practice you can use it as if it were class-based; in fact, before the addition of Object.create() with ES5, you only could get proper prototypal inheritance through non-standard extensions like __proto__ or a hack using temporary constructors.
There's no syntactic support for class-based inheritance, so it's a bit verbose, but not really complicated:
function AClass(foo) {
this.foo = foo;
}
// methods are shared between instances
AClass.prototype.alertFoo = function() {
alert(this.foo);
};
function ASubClass(foo, bar) {
// call parent constructor
AClass.call(this, foo);
this.bar = bar;
}
// simulate inheritance via method aggregation
for(var name in AClass.prototype) {
if(AClass.prototype.hasOwnProperty(name))
ASubClass.prototype[name] = AClass.prototype[name];
}
// alternatively, use proper inheritance
ASubClass.prototype = Object.create(AClass.prototype);
ASubClass.prototype.alertFooBar = function() {
alert(this.foo + ' ' + this.bar);
};
This is what I'd call the idiomatic way to implement classes in Javascript.
Instead of adding methods to the prototype, you can also add them to the instance within the constructor. This way, you can simulate private members as such methods close over the constructor's lexical scope -- but this comes with a performance penalty.
Most custom class implementations just provide sugar over these patterns.
- chmike 15y agoIn your example cygx, this.foo is a public member variable. As you say, it is possible to have private member variables but this implies some constrains. The following example illustrate how one may have private and public members as well as private and public methods and how to access them. function AClass(foo) { this.foo = foo; // public member variable var bar = "bar"; // private member variable function fun1() // private method { bar = this.foo; // private and public var access } this.fun2 = function () // public privileged method { bar = this.foo; // private and public var access } } A public method defined with prototype doesn't allow to access private member variables. This is the difference between privileged methods and public methods. The privileged method can access private methods because of closure. This is all very different from other OOP languages. I just add these for clarification. It may be helpful to some readers. By convention one may also add an underscore in front of private members and function identifiers to make the difference clearly visible in the code. Would Object.create also inherit private functions and members ?
- cygx 15y agoWould Object.create also inherit private functions and members ? No, it would not - these so-called private members and methods have nothing to do with inheritance, but rather lexical closure. However, as the super constructor is called, priviledged methods will be present and still have access to the private variables. See also http://stackoverflow.com/a/1441692/48015 http://stackoverflow.com/a/1441692/48015 for a more comprehensive overview over different access levels.
- chmike 15y agoThank you very much. It's the first time I see this pattern and a clear specification. I used privileged methods everywhere instead of shared public methods based on this article: http://javascript.crockford.com/private.html http://javascript.crockford.com/private.html The missing infos in the StackOverflow answer are how do one instantiate such class and access it's methods and public and shared members ? var obj = new MyObj() ? obj.publicSharedVar ?