DRY-er Javascript Classes - javascript

Using jQuery, this is the format of most of the classes I write in JS:
$.Tabs = function(options){
var self = this;
this.defaults = {};
var cfg = $.extend(true, {}, this.defaults, options);
this.$elem = cfg.$elem;
function _init(){
var dontInit = false;
if (!cfg.$elem || !cfg.requiredProperty){
alert('missing params');
dontInit = true;
}
if (!dontInit){
self.$elem.bridge(self);
}
}
this.show = function(){};
this.hide = function(){};
_init();
}
The code above is just an example by the way.
My question is, how do you extrapolate common tasks/functionality from your classes, so every new class you write, you don't have to retype everything again?
I created a Class creation script based off of John Resig's Simple Javascript Inheritance pattern, which allows you to require certain parameters, bind event listeners for a pub/sub pattern, automatically combine defaults with options passed in, and it creates a bridge between the DOM element and the class instance (i.e $('elem').data('instanceNamespace', classInstance);)
But I'm uncomfortable with continuously using this class script to write my classes because it makes them less portable. But yet, I don't want all my classes to have so many similarities between them when it feels like those aspects can be abstracted.
Thoughts? Or how do you format your Javascript classes?
Thanks in advance.
Edit: Also, would anyone know the impact using a class creation script has on performance? I'm assuming the extra closures adds overhead but is it enough to make it not worthwhile to use?

I think the idea you are looking for is called a Mix-in.
Note: what follows is just vanilla javascript, no jQuery, but I think you'll see that prototype inheritance is very well suited to the idea of mixins.
Let's say you define a simple constructor:
var Person = function(name){
this.name=name;
this.sayhello = function(){
console.log(this.name + ' says hello');
};
};
Then we can mixin new abilities by copying the properties over to the new object with the function below:
var extend = function(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
};
We can create some useful abilities that we may want to re-use for lots of different classes, so instead of having them all inherit from a common class, we can just mixin the new abilities at runtime:
var DanceMixin = {
dance: function(){
console.log(this.name + ' is dancing!');
}
};
var SingMixin = {
sing: function(){
console.log(this.name + ' is singing!');
}
};
var bob = new Person('bob');
extend(bob, SingMixin);
extend(bob, DanceMixin);
bob.sing();
/* bob is singing! */
bob.dance();
/* bob is dancing! */
bob.sayhello();
/* bob says hello */
Note that this is adding the new abilities to only a single object. If we wanted to add these abilities to all Person objects, we would need to modify the Person prototype.
Now let's say we have another trivial constructor for Animals:
var Animal = function(name){
this.name = name;
this.roar = function(){
console.log(this.name + ' is roaring!');
};
};
And let's say we want all of our animals to have the ability to dance. So we can add the DanceMixin to the Animal prototype using a function such as:
var mixin = function(dest, src){
for (var property in src)
dest.prototype[property] = src[property];
return dest;
}
mixin(Animal, DanceMixin);
Now we can make some animals that can all dance...
var lion = new Animal('lion');
lion.dance()
/* lion is dancing! */
By the way, I highly recommend you check out the MooTools approach to the problem, which is quite elegant. Here is an example of using Implements in MooTools classes to facilitate mixins.

Related

Javascript inheritance and encapsulation, done efficiently

Coming from a C++ / Objective-C background, I'm trying to learn how to correctly and efficiently reproduce the patterns of inheritance and encapsulation in Javascript. I've done plenty of reading (Crockford etc.) and while there are plenty of examples of how to achieve one or the other, I'm struggling with how to combine them without introducing significant negatives.
At the moment, I have this code:
var BaseClass = (function() {
function doThing() {
console.log("[%s] Base-class's 'doThing'", this.name);
}
function reportThing() {
console.log("[%s] Base-class's 'reportThing'", this.name);
}
return function(name) {
var self = Object.create({});
self.name = name;
self.doThing = doThing;
self.reportThing = reportThing;
return self;
}
}());
var SubClass = (function(base) {
function extraThing() {
console.log("[%s] Sub-class's 'extraThing'", this.name);
}
function doThing() {
console.log("[%s] Sub-class's replacement 'doThing'", this.name);
}
return function(name) {
// Create an instance of the base object, passing our 'name' to it.
var self = Object.create(base(name));
// We need to bind the new method to replace the old
self.doThing = doThing;
self.extraThing = extraThing;
return self;
}
}(BaseClass));
It mostly does what I want:
// Create an instance of the base class and call it's two methods
var base = BaseClass("Bert");
base.doThing(); // "[Bert] Base-class's 'doThing'"
base.reportThing(); // "[Bert] Base-class's 'reportThing'"
var other = BaseClass("Fred");
// Create an instance of the sub-class and call it's three methods (two from the base, one of it's own)
var sub = SubClass("Alfred");
sub.doThing(); // "[Alfred] Sub-class's replacement 'doThing'"
sub.extraThing(); // "[Alfred] Sub-class's 'extraThing'"
sub.reportThing(); // "[Alfred] Base-class's 'reportThing'"
But, there's (at least!) two issues:
I'm not convinced the prototype chain is intact. If I substitute a method in the prototype via one instance of a sub-class, other instances don't see it:
No encapsulation of .name property
I'm replacing the prototype's implementation of a function like this:
Object.getPrototypeOf(oneInstance).reportThing = function() { ... }
otherInstance.reportThing() // Original version is still called
That's perhaps not a significant problem, but it is causing me to doubt my understanding.
Private variables is something I want to implement efficiently though. The module pattern of variable hiding doesn't help here, as it causes function definitions to exist per-object. I'm probably missing a way of combining patterns, so is there a way of achieving private variables without duplicating functions?
This is usually how I tackle inheritance and encapsulation in JavaScript. The defclass function is used to create a new class that doesn't inherit from any other class and the extend function is used to create a new class which extends another class:
var base = new BaseClass("Bert");
base.doThing(); // "Bert BaseClass doThing"
base.reportThing(); // "Bert BaseClass reportThing"
var sub = new SubClass("Alfred");
sub.doThing(); // "Alfred SubClass replacement doThing"
sub.extraThing(); // "Alfred SubClass extraThing"
sub.reportThing(); // "Alfred BaseClass reportThing"
var other = new SubClass("Fred");
SubClass.prototype.reportThing = function () {
console.log(this.name + " SubClass replacement reportThing");
};
other.reportThing(); // Fred SubClass replacement reportThing
<script>
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
function extend(constructor, keys) {
var prototype = Object.create(constructor.prototype);
for (var key in keys) prototype[key] = keys[key];
return defclass(prototype);
}
var BaseClass = defclass({
constructor: function (name) {
this.name = name;
},
doThing: function () {
console.log(this.name + " BaseClass doThing");
},
reportThing: function () {
console.log(this.name + " BaseClass reportThing");
}
});
var SubClass = extend(BaseClass, {
constructor: function (name) {
BaseClass.call(this, name);
},
doThing: function () {
console.log(this.name + " SubClass replacement doThing");
},
extraThing: function () {
console.log(this.name + " SubClass extraThing");
}
});
</script>
Read the following answer to understand how inheritance works in JavaScript:
What are the downsides of defining functions on prototype this way?
It explains the difference between prototypes and constructors. In addition, it also shows how prototypes and classes are isomorphic and how to create “classes” in JavaScript.
Hope that helps.
The simple recipe follows:
function BaseClass(someParams)
{
// Setup the public properties, e.g.
this.name = someParams.name;
}
BaseClass.prototype.someMethod = function(){
// Do something with the public properties
}
Now the inheritance occurs this way
function SubClass(someParams)
{
// Reuse the base class constructor
BaseClass.call(this, someParams);
// Keep initializing stuff that wasn't initialized by the base class
this.anotherProperty= someParams.anotherProperty;
}
// Copy the prototype from the BaseClass
SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;
// Start extending or overriding stuff
SubClass.prototype.someMethod = function(){
// In case you still wanna have the side effects of the original method
// This is opt-in code so it depends on your scenario.
BaseClass.prototype.someMethod.apply(this, arguments);
// Override the method here
}
Taken from:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
P.S. Object.create may not be supported on all old browsers, but don't worry, there's a polyfill for that in this link. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
If you want to preserve the prototype chain, you must override and use .prototype:
Example:
Main Class:
function BaseClass(){
}
BaseClass.prototype.doThing = function(){...}
SubClass:
function SubClass(){
}
SubClass.prototype= new BaseClass();
SubClass.prototype.extraThing = function(){};
Now, whenever you change extraThing or doThing it gets replaced everywhere.
The name property is accessible as a public variable (it's not static).
If you want it static, you must put it in prototype.
If you want it private, you mast make it function local:
function BaseClass(nameParam){
var name = nameParam;
}
To create an object simply call the function:
var testObj = new BaseClass("test");
testObj.doThing();
If you want to combine private variables with rewritable functions, you might find your answer here. But if you are able to rewrite the function that has access to the private variable, it's not really a private variable anymore.

How can I extend a class defined behind a closure in JavaScript?

I have a set of JavaScript "classes" where a base class defines functions that are then shared by an inherited class. It is working, and it is set up like this:
var ThingA = function(name) {
this.name = name;
};
ThingA.prototype = {
sayHi: function() {
alert('Hi, ' + this.name + '!');
}
};
var ThingB = function() {
ThingA.call(this, 'Charlie');
};
ThingB.prototype = new ThingA();
ThingB.prototype.constructor = ThingB;
var instanceOfB = new ThingB();
instanceOfB.sayHi(); // alerts 'Hi, Charlie!'
For reasons that are outside of my control, my company prefers to follow this pattern when writing JavaScript:
SomeClass = function() {
// "Private" functions go here
function somePrivateMethod() {
...
}
return {
// "Public" methods go here
somePublicMethod: function() { ... }
};
}();
Now, this is fine as far as things go, and it works well for many situations. But it is more of a functional style. There is only one "class" instance, and everything is static.
I've been asked to modify my working code to more closely match the style my company prefers. So my question is, there a way to inherit from a class that is wrapped inside a factory class? It would look something like this:
FactoryClassA = function() {
var ThingA = function(name) {
this.name = name;
};
ThingA.prototype = {
sayHi: function() {
alert('Hi, ' + this.name + '!');
}
};
return {
createThingA: function(name) {
return new ThingA(name);
}
};
}();
FactoryClassB = function() {
// Define a ThingB class that inherits from ThingA somehow
return {
createThingB: function() {
return new ThingB();
}
};
}();
var instanceOfB = FactoryClassB.createThingB();
instanceOfB.sayHi(); // should alert 'Hi, Charlie!'
Is there a way to define ThingB wrapped in FactoryClassB that inherits from ThingA wrapped in FactoryClassA? Thanks to this question, I know that I'm not going to be able to do it exactly like this. I am thinking of using a method to extend a given class ... somehow?
This answer seems close, but I'm having trouble figuring out the details of how to modify that example to fit with the specifics of my situation. I am willing to bend my company's usual pattern a little bit, but can I at least get closer to it?
UPDATE 1
In response to Adam's comment to just add a parameter to the factory class, here's where I'm stuck:
ThingB.prototype = new ThingA();
ThingB.prototype.constructor = ThingB;
I can't figure out how to adapt these lines to make it work if I just pass in a parameter to the factory class method.
Below is what (I believe) you're looking for:
FactoryClassA = function() {
var ThingA = function(name) {
this.name = name;
};
ThingA.prototype = {
sayHi: function() {
console.log('Hi, ' + this.name + '!');
}
};
// Add the constructor back to the prototype
// (see explanation below)
ThingA.prototype.constructor = ThingA;
return {
createThingA: function(name) {
return new ThingA(name);
}
};
}();
FactoryClassB = function() {
// Bootstrapping:
// Capture the instance, as we'll need it to set up the prototype
var baseInstance = new FactoryClassA.createThingA();
// Capture the constructor
var baseConstructor = baseInstance.constructor;
// Keep a reference to the base prototype
var baseProto = baseConstructor.prototype;
function ThingB(name) {
// Call base constructor, along with our args
baseConstructor.call(this, name);
};
ThingB.prototype = baseInstance;
ThingB.prototype.constructor = ThingB;
ThingB.prototype.sayHi = function() {
console.log('here I am');
// call the base class `sayHi`
baseProto.sayHi.call(this);
};
return {
createThingB: function(name) {
return new ThingB(name);
}
};
}();
// Testing
var foo = FactoryClassB.createThingB("Indeed");
foo.sayHi();
// Output:
// here I am
// hi indeed
Explanation:
in FactoryClassA, this line is necessary:
ThingA.prototype.constructor = ThingA;
Note that every prototype in JS is automatically created with a reference to its constructor. For example, when you do:
function T(){}
T.prototype already has a property called constructor which points back to T.
However, in your implementation of ThingA, you reset the entire prototype, by doing ThingA.prototype = { ... }. Therefore, you now have lost the reference to its constructor. In 99% of cases it is ok, and won't have any negative side effects (which is probably why most developers tend to forget it). However, in the case of inheritance, it may be necessary.
Now, within FactoryClassB, we need to do some bootstrapping:
var baseInstance = new FactoryClassA.createThingA();
var baseConstructor = baseInstance.constructor;
var baseProto = baseConstructor.prototype;
Observe the last two lines, as they are pivotal to achieving inheritance in this design pattern. First, since ThingA's constructor is accessible via the prototype (ThingA.prototype.constructor = ThingA), then it means that given an instance of ThingA, we can directly retrieve its constructor. Since the constructor is the function itself, and since every function has a reference to its prototype, we can keep a reference of ThingA.prototype with baseConstructor.prototype.
Next is the critical part, where we set up the inheritance chain:
function ThingB(name) {
// Call the base constructor
baseConstructor.call(this, name);
};
ThingB.prototype = baseInstance;
ThingB.prototype.constructor = ThingB;
The last line above is quite important, as it tells the prototype what its constructor is, otherwise it would still point to ThingA.
There you have it - prototypal inheritance.
Side note:
You can probably see how the above can get quite tedious, a little grotesque, and repetitive. Ergo, you might want to consider an inheritance library like Fiber.js which follows the encapsulation pattern you desired (along with some bonuses like mixins and decorators). Disclaimer: I authored the library.

How to achieve pseudo-classical inheritance right on the class declaration? [duplicate]

This question already has answers here:
How to implement C# access modifiers in javascript?
(5 answers)
Closed 1 year ago.
Note:
As the answers tell, the code proposed in the question does NOT really achieve inheritance(otherwise it becomes an answer rather than a question .. ) due to some issues described in the question and in my comments. It works as expected as a fake of inheritance(and not even prototypal).
Summary
In short, make it as similar as we are writing a general OO language rather than javascript, but keep the inheritance be correct.
The story
Object.create is a good way to achieve prototypal inheritance, but it's a bit confusing to a typed brain and new fans.
There are various ways that we can write javascript code more like we are writing other OO languages with the pseudo-classical pattern. As it's pseudo-classical, we must deal with the underlying prototypal inheritance of javascript correctly.
What I want to find is an approach that the pseudo-classical inheritance can be achieved right on the class declaration. The code for demonstration is put at the rear of the post, it works as expected, however, there are some annoying things:
I cannot get rid of return in the class declaration or the inheritance won't work.
I have no way except pass this in the class declaration to make the returning closure know what is this.
I also want to get rid of function (instance, _super) {, but not yet have a good idea.
The static(own properties) of a class are not inherited.
A solution would be more of some syntactic sugar than the existing frameworks, a good pattern is applicable.
The _extends function:
function _extends(baseType) {
return function (definition) {
var caller=arguments.callee.caller;
var instance=this;
if(!(instance instanceof baseType)) {
(caller.prototype=new baseType()).constructor=caller;
instance=new caller();
}
var _super=function () {
baseType.apply(instance, arguments);
};
definition(instance, _super);
return instance;
};
}
The Abc class:
function Abc(key, value) {
return _extends(Object).call(this, function (instance, _super) {
instance.What=function () {
alert('What');
};
instance.getValue=function () {
return 333+Number(value);
};
instance.Value=instance.getValue();
instance.Key=key;
});
}
The Xyz class:
function Xyz(key, value) {
return _extends(Abc).call(this, function (instance, _super) {
_super(key, value);
instance.That=function () {
alert('That');
};
});
}
Example code:
var x=new Xyz('x', '123');
alert([x.Key, x.Value].join(': ')+'; isAbc: '+(x instanceof Abc));
var y=new Xyz('y', '456');
alert([y.Key, y.Value].join(': ')+'; isAbc: '+(y instanceof Abc));
var it=new Abc('it', '789');
alert([it.Key, it.Value].join(': ')+'; isAbc: '+(it instanceof Abc));
alert([it.Key, it.Value].join(': ')+'; isXyz: '+(it instanceof Xyz));
x.What();
y.That();
it.What();
it.That(); // will throw; it is not Xyz and does not have That method
No. No. No. This won't do. You're doing inheritance in JavaScript all wrong. Your code gives me migraines.
Creating a Pseudo-Classical Inheritance Pattern in JavaScript
If you want something similar to classes in JavaScript then there are a lot of libraries out there which provide it to you. For example using augment you could restructure your code as follows:
var augment = require("augment");
var ABC = augment(Object, function () {
this.constructor = function (key, value) {
this.key = key;
this.value = value;
};
this.what = function () {
alert("what");
};
});
var XYZ = augment(ABC, function (base) {
this.constructor = function (key, value) {
base.constructor.call(this, key, value);
};
this.that = function () {
alert("that");
};
});
I don't know about you but to me this looks a lot like classical inheritance in C++ or Java. If this solves your problem, great! If is doesn't then continue reading.
Prototype-Class Isomorphism
In a lot of ways prototypes are similar to classes. In fact prototypes and classes are so similar that we can use prototypes to model classes. First let's take a look at how prototypal inheritance really works:
The above picture was taken from the following answer. I suggest you read it carefully. The diagram shows us:
Every constructor has a property called prototype which points to the prototype object of the constructor function.
Every prototype has a property called constructor which points to the constructor function of the prototype object.
We create an instance from a constructor function. However the instance actually inherits from the prototype, not the constructor.
This is very useful information. Traditionally we've always created a constructor function first and then we've set its prototype properties. However this information shows us that we may create a prototype object first and then define the constructor property on it instead.
For example, traditionally we may write:
function ABC(key, value) {
this.key = key;
this.value = value;
}
ABC.prototype.what = function() {
alert("what");
};
However using our newfound knowledge we may write the same thing as:
var ABC = CLASS({
constructor: function (key, value) {
this.key = key;
this.value = value;
},
what: function () {
alert("what");
}
});
function CLASS(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
As you can see encapsulation is easy to achieve in JavaScript. All you need to do is think sideways. Inheritance however is a different issue. You need to do a little more work to achieve inheritance.
Inheritance and Super
Take a look at how augment achieves inheritance:
function augment(body) {
var base = typeof this === "function" ? this.prototype : this;
var prototype = Object.create(base);
body.apply(prototype, arrayFrom(arguments, 1).concat(base));
if (!ownPropertyOf(prototype, "constructor")) return prototype;
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
Notice that the last three lines are the same as that of CLASS from the previous section:
function CLASS(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
This tells us that once we have a prototype object all we need to do is get its constructor property and return it.
The first three lines of augment are used to:
Get the base class prototype.
Create a derived class prototype using Object.create.
Populate the derived class prototype with the specified properties.
That's all that there is to inheritance in JavaScript. If you want to create your own classical inheritance pattern then you should be thinking along the same lines.
Embracing True Prototypal Inheritance
Every JavaScript programmer worth their salt will tell you that prototypal inheritance is better than classical inheritance. Nevertheless newbies who come from a language with classical inheritance always try to implement classical inheritance on top of prototypal inheritance, and they usually fail.
They fail not because it's not possible to implement classical inheritance on top of prototypal inheritance but because to implement classical inheritance on top of prototypal inheritance you first need to understand how true prototypal inheritance works.
However once you understand true prototypal inheritance you'll never want to go back to classical inheritance. I too tried to implement classical inheritance on top of prototypal inheritance as a newbie. Now that I understand how true prototypal inheritance works however I write code like this:
function extend(self, body) {
var base = typeof self === "function" ? self.prototype : self;
var prototype = Object.create(base, {new: {value: create}});
return body.call(prototype, base), prototype;
function create() {
var self = Object.create(prototype);
return prototype.hasOwnProperty("constructor") &&
prototype.constructor.apply(self, arguments), self;
}
}
The above extend function is very similar to augment. However instead of returning the constructor function it returns the prototype object. This is actually a very neat trick which allows static properties to be inherited. You can create a class using extend as follows:
var Abc = extend(Object, function () {
this.constructor = function (key, value) {
this.value = 333 + Number(value);
this.key = key;
};
this.what = function () {
alert("what");
};
});
Inheritance is just as simple:
var Xyz = extend(Abc, function (base) {
this.constructor = function (key, value) {
base.constructor.call(this, key, value);
};
this.that = function () {
alert("that");
};
});
Remember however that extend does not return the constructor function. It returns the prototype object. This means that you can't use the new keyword to create an instance of the class. Instead you need to use new as a method, as follows:
var x = Xyz.new("x", "123");
var y = Xyz.new("y", "456");
var it = Abc.new("it", "789");
This is actually a good thing. The new keyword is considered harmful and I strongly recommend you to stop using it. For example it's not possible to use apply with the new keyword. However it is possible to use apply with the new method as follows:
var it = Abc.new.apply(null, ["it", "789"]);
Since Abc and Xyz are not constructor functions we can't use instanceof to test whether an object is an instance of Abc or Xyz. However that's not a problem because JavaScript has a method called isPrototypeOf which tests whether an object is a prototype of another object:
alert(x.key + ": " + x.value + "; isAbc: " + Abc.isPrototypeOf(x));
alert(y.key + ": " + y.value + "; isAbc: " + Abc.isPrototypeOf(y));
alert(it.key + ": " + it.value + "; isAbc: " + Abc.isPrototypeOf(it));
alert(it.key + ": " + it.value + "; isXyz: " + Xyz.isPrototypeOf(it));
In fact isPrototypeOf is more powerful than instanceof because it allows us to test whether one class extends another class:
alert(Abc.isPrototypeOf(Xyz)); // true
Besides this minor change everything else works just like it did before:
x.what();
y.that();
it.what();
it.that(); // will throw; it is not Xyz and does not have that method
See the demo for yourself: http://jsfiddle.net/Jee96/
What else does true prototypal inheritance offer? One of the biggest advantages of true prototypal inheritance is that there's no distinction between normal properties and static properties allowing you to write code like this:
var Xyz = extend(Abc, function (base) {
this.empty = this.new();
this.constructor = function (key, value) {
base.constructor.call(this, key, value);
};
this.that = function () {
alert("that");
};
});
Notice that we can create instances of the class from within the class itself by calling this.new. If this.constructor is not yet defined then it returns a new uninitialized instance. Otherwise it returns a new initialized instance.
In addition because Xyz is the prototype object we can access Xyz.empty directly (i.e. empty is a static property of Xyz). This also means that static properties are automatically inherited and are no different from normal properties.
Finally, because the class is accessible from within the class definition as this, you can created nested classes which inherit from the class which they are nested within by using extend as follows:
var ClassA = extend(Object, function () {
var ClassB = extend(this, function () {
// class definition
});
// rest of the class definition
alert(this.isPrototypeOf(ClassB)); // true
});
See the demo for yourself: http://jsfiddle.net/Jee96/1/
There's an exhaustive tutorial on how to do what you're after.
oop-concepts
pseudo-classical-pattern
all-one-constructor-pattern
I know this doesn't answer your question because as far as I know there is no good way to put everything in the function constructor and have it use prototype.
As I've commented; if you have trouble with the JavaScript syntax then typescript could be a good alternative.
Here is a helper function that I use for inheritance and overriding (calling super) using JavaScript (without Object.create)
var goog={};//inherits from closure library base
//http://docs.closure-library.googlecode.com/git/closure_goog_base.js.source.html#line1466
// with modifications for _super
goog.inherits = function(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
// modified _super
childCtor.prototype._super = parentCtor.prototype;
};
// Parent class dev
var Parent = function(){};
Parent.prototype.sayHi=function(){
console.log("hi from Parent");
}
// end class
// Child class dev
var Child = function(){}
goog.inherits(Child,Parent);
Child.prototype.sayHi=function(){
//_super only works on parent.prototype
//this is where functions are usually defined
//have to add this. to call _super as well
this._super.sayHi();
console.log("hi from Child");
}
// end Child
//code to test
var c = new Child();
c.sayHi();//hi from Parent and hi from Child
Even if you find a way to write helper functions and make JS constructor functions look like Java classes you have to understand prototype.
You can always try jOOP, though it does require jQuery.
https://github.com/KodingSykosis/jOOP
var myClass = $.cls({
main: function() {
$('body').append('My App is loaded <br/>');
}
});
var mySecondClass = $.cls({
main: function() {
this._super();
$('body').append('My Second App is loaded <br/>');
}
}, myClass);
var app = new mySecondClass();
http://jsfiddle.net/kodingsykosis/PrQWu/
I believe you are looking for more functionality than this, but if you want to just inherit a bunch of methods from another class you could do this
http://cdpn.io/Jqhpc
var Parent = function Parent () {
this.fname = 'Bob';
this.lname = 'Jones';
};
Parent.prototype.getFname = function getFname () {
return this.fname;
};
Parent.prototype.getLname = function getLname () {
return this.lname;
};
var Child = function Child () {
this.fname = 'Jim';
};
Child.prototype = Parent.prototype;
var child = new Child();
document.write(child.getFname()); //=> Jim

How to extend a class in JavaScript

I'm working on a chess game built in JavaScript. I'm taking an object-oriented approach to it and am having some difficulty working with JavaScript's inheritance. I want there to be a "Piece" abstract class that holds some fields and basic getters/setters such as is this piece black or white. I then want to have classes for each type of piece that I can instantiate like so:
var pieceOne = new Pawn();
The Pawn() should have all the fields and methods of Piece but have its own method for movement, and additional fields (such as whether or not it has moved yet, as this doesn't matter for most pieces). Here's my current Piece class:
//This object specifies basic information about pieces.
"use strict";
function Piece(color, type, captured, hasMoved) {
this.color = color;
this.type = type;
this.captured = captured;
this.hasMoved = hasMoved;
this.image = color + "_" + type + ".svg";
}
Piece.prototype.getImage = function getImage(){
return this.image;
}
Piece.prototype.isCaptured = function isCaptured(){
return this.captured;
};
I know if I am going to make a subclass for every kind of piece that I'd probably eliminate the "type" field, but how could I make a Pawn subclass? Something like this?
function Pawn() = new Piece(color, captured, hasMoved);
Pawn.prototype.getLegalMoves = function getLegalMoves(){
//return legal moves
}
var pieceOne = new Pawn("black", false, false);
Extending a class can be done in different ways. The simplest method to extend an class is to use Object.create method. This is common method which is used to achieve abstraction (Link to my blog). Let's give an example of the Object.create method as follows.
var Logger = { log : function(log){} }
var ConsoleLogger = function() {};
ConsoleLogger.prototype = Object.create(Logger);
If you are willing to take an object oriented approach on JS I would recommend you to follow the power constructor pattern.
Basically you have a function that creates objects for you and take advantage of the closures to hide the internal properties (fields or methods).
function myObject(){
var that={};
var myPrivateField;
var myPrivateFunction=function(){
}
that.myPublicMethod=function(){
}
return that;
}
Then you can just call the method myObject() and you will get a new object of this type.
You can extend this example to use inheritance by just calling the power constructor of another object and then use object augmentation. Take a look at the example of parasatic inheritance of Douglas Crockford.
You can call Piece's constructor from Pawn and have that constructor operate on the Pawn instance:
function Pawn(/* args... */) {
Piece.call(this, color, type, captured, hasMoved);
/* Pawn-specific constructor code... */
}
I believe it's just a matter of setting the prototype of the specific piece constructors to an instance of Piece. For example:
Pawn.prototype = new Piece("", false, false);
However, this will not call the Piece (super) constructor every time you instantiate a new Pawn, so you'll have to manually assign color, type, etc. from the Pawn constructor:
-- EDIT --
You might prefer this instead: Javascript inheritance: call super-constructor or use prototype chain?
Take a look at this: https://github.com/haroldiedema/joii
var BaseClass = function()
{
this.some_var = "foobar";
/**
* #return string
*/
this.someMethod = function() {
return this.some_var;
}
};
var MyClass = new Class({ extends: BaseClass }, function()
{
/**
* #param string value
*/
this.__construct = function(value)
{
this.some_var = value;
}
})
Usage:
var obj = new MyClass("Hello World!");
console.log( obj.someMethod() ); // Hello World!

Is this a good decorator pattern for javascript?

I need some simple objects that could become more complex later, with many different properties, so i thought to decorator pattern.
I made this looking at Crockford's power constructor and object augmentation:
//add property to object
Object.prototype.addProperty = function(name, func){
for(propertyName in this){
if(propertyName == name){
throw new Error(propertyName + " is already defined");
}
}
this[name] = func;
};
//constructor of base object
var BasicConstructor = function(param){
var _privateVar = param;
return{
getPrivateVar: function(){
return _privateVar;
}
};
};
//a simple decorator, adds one private attribute and one privileged method
var simpleDecorator = function(obj, param){
var _privateVar = param;
var privilegedMethod1 = function(){
return "privateVar of decorator is: " + _privateVar;
};
obj.addProperty("privilegedMethod1", privilegedMethod1);
return obj;
}
//a more complex decorator, adds public and private properties
var complexDecorator = function(obj, param1, param2){
//private properties
var _privateVar = param1;
var _privateMethod = function(x){
for(var i=0; i<x; i++){
_privateVar += x;
}
return _privateVar;
};
//public properties
var publicVar = "I'm public";
obj.addProperty("publicVar", publicVar);
var privilegedMethod2 = function(){
return _privateMethod(param2);
};
obj.addProperty("privilegedMethod2", privilegedMethod2);
var publicMethod = function(){
var temp = this.privilegedMethod2();
return "do something: " + temp + " - publicVar is: " + this.publicVar;
};
obj.addProperty("publicMethod", publicMethod);
return obj;
}
//new basic object
var myObj = new BasicConstructor("obj1");
//the basic object will be decorated
var myObj = simpleDecorator(obj, "aParam");
//the basic object will be decorated with other properties
var myObj = complexDecorator(obj, 2, 3);
Is this a good way to have Decorator Pattern in javascript?
Are there other better ways to do this?
There are various implementations of the Decorator pattern in Javascript on Wikipedia and other sites - (1), (2), (3). The pattern is defined as:
the decorator pattern is a design pattern that allows new/additional behaviour to be added to an existing object dynamically.
Object extension is already build into the language itself. Objects can be easily extended, and properties can be added anytime. So why should you have to jump through hoops to achieve this? Shouldn't something like this suffice:
var person = { name: "Jack Bauer" };
// Decorated the object with ability to say a given phrase
person.say = function(phrase) {
alert(phrase);
}
// Using the decorated functionality
person.say("Damn it!");
If you want a method to apply to all objects that were created using this function, then add that method/properties to the function's prototype.
Update: If you have clearly defined pieces of functionality which can be mixed and matched as needed into certain types of objects, then the MooTools approach of extending and mixing in behavior into objects is nicely done. To give an example, consider a UI component that can be resized, dragged around with a handle, and deleted by clicking a tick mark at the top-right corner. You may not want to create each component with these behaviors but define all these behaviors separately each into their own object. And later mix in these behaviors into each type of component as needed.
var Resizable = {
...
};
var Draggable = {
...
};
var Deletable = {
...
};
var someLabel = new Label("Hello World");
// one way to do it
someLabel.implement([Resizable, Draggable, Deletable]);
// another way to do it
someLabel.implement(Resizable);
someLabel.implement(Draggable);
someLabel.implement(Deletable);
It looks better and more intuitive (to me) than doing something like
var awesomeLabel = new Resizable(new Draggable(new Deletable(someLabel)));
because we are still dealing with a label, and not some resizable, or some draggable, or some deletable object. Another small point, but still worth mentioning is that the parentheses start getting unmanageable after 3 or 4 decorators, especially without good IDE support.

Categories