Let's say I have two classes, Base and Child. Base is the base class that Child will be inheriting from. Here's the code to visualize this:
Base.js
function Base(init) {
}
function log() {
console.log('here');
}
Base.prototype.log = log;
module.exports = Base;
Child.js
var Base = require('../Base.js');
var Child = module.exports = function Child(init) {
Base.call(this, init);
};
require('util').inherits(Child, Base);
function test() {
this.log(); // doesn't work
Base.prototype.log(); // Works but is quite ugly
Child.super_.prototype.log(); // Works but is even uglier
}
Child.prototype.test = test;
What I would absolutely love to do is something like this.log() or even log() would be nice. I realize I can set a variable to that in my inherited class, but then I would have to do that for every class that inherits Base, which is definitely not ideal. So my question is, can I do something like this.log() without having to set a variable in the inherited class? Am I misunderstanding something?
Updated Answer:
From your comment below, replying to my statment that this.log() should work:
Well, so that's the thing. When I'm in Child's test function, this is an empty object, so I'm assuming somewhere down the line I'm not getting the proper scope.
You haven't shown how you're calling test, but I suspect that's where the problem is. Provided you call it via a Child instance:
var c = new Child();
c.test();
...then within the call, this will be the child instance, which will inherit (indirectly) the Parent.prototype object with its log property.
But how you call it is important. This wouldn't work, for instance:
var c = new Child();
var f = c.test;
f();
If you do that, within the call to the function, this will be the global object (or undefined if you're in strict mode), not a Child instance. This is because in JavaScript, this is set primarily by how a function is called, and calling it like that doesn't set this to what you want.
This matters for callbacks, because passing in c.test as a callback:
someFunctionThatUsesACallback(c.test);
...means the code calling back won't set this for you.
If you need to do that, Function#bind will help:
var f = c.test.bind(c); // Returns a version of c.test that, when called,
// will have `this` set to `c`
f(); // Works, `this` is the `Child` instance
And similarly:
someFunctionThatUsesACallback(c.test.bind(c));
More (on my blog):
Mythical methods
You must remember this
Original Answer:
If you set up the prototype hierarchy correctly, and Child.prototype doesn't have log on it (and you don't put a log property on instances), then you should be able to use this.log(); just fine. If you can't, then the hierarchy hasn't been set up correctly.
I don't know what util.inherits does, but setting up the relationship between Child and Parent correctly isn't complicated:
function Parent() {
}
Parent.prototype.log = function() {
console.log("log called");
};
function Child () {
Parent.call(this);
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // This line is largely optional, but a good idea
// Usage
var c = new Child();
c.log(); // "log called"
But if you override log in your Child.prototype or assign a log property to instances, and you want to use Parent's version of log, then of course you can't just use this.log() because the property doesn't refer to Parent.prototype.log anymore.
When you need to call the parent version of something (I call them "supercalls," and I don't think that's original), you have to do more work:
I usually set up hierarchies like this by passing the parent constructor into a function I use to build the child, e.g.:
var Child = (function(Super) {
var pp = Super.prototype;
function Child() {
}
Child.prototype = Object.create(pp);
Child.prototype.doSomething = function() {
// Call `log` with appropriate `this`
pp.log.call(this);
};
return Child;
})(Parent);
By always using that pattern, I avoid having to write Parent inside the Child code (I use the Super arg instead), so if I need to rebase Child, I just change what I pass into the function.
Because that's fairly ugly (for instance, it's unclear at the top of Child that it derives from Parent, since Parent is at the bottom) and involves boilerplate code I don't feel the need to write again every time, I wrote a simple helper script for it I call Lineage, which makes it look like this:
var Child = Lineage.define(Parent, function(p, pp) {
p.doSomething = function() {
// Call `log` with appropriate `this`
pp.log.call(this);
};
});
Note that Lineage passes in both the Child and Parent prototypes as arguments, making it concise to use them (and since you get to pick those argumetn names, you can use whatever terminology works for you — I use p for the prototype of the "class" being created [Child in the above], and pp for the parent's prototype, etc.).
The standard inherits function from node.js is (in my humble opinion) very bad code. Instead I prefer to use augment to create classes:
// base.js
var augment = require("augment");
var Base = module.exports = augment(Object, function () {
this.constructor = function (init) {
};
this.log = function () {
console.log("here");
};
});
// child.js
var augment = require("augment");
var Base = require("./base");
var Child = module.exports = augment(Base, function (base) {
this.constructor = function (init) {
base.constructor.call(this, init);
};
this.test = function () {
this.log();
};
});
In addition augment.js is just 20 lines of code and can be used everywhere.
Just as an FYI, I ended up putting this in the global variable that Node creates for you. I realize that's bad practice, but it's a logging mechanism that needs to be used by any class, controller, etc., so I don't think it's that terrible of a solution.
However, in Compound, you can create no_eval controllers, which means they look like typical prototypical functions... so you can essentially create a mixin, or I can require my mixin and use it like a class... like this:
var ControllerMixin = require(process.cwd() + 'app/mixins/ControllerMixin.js');
var Log;
var LoggerController = module.exports = function LoggerController(init) {
ControllerMixin.call(this, init); // mixin approach
Log = require(process.cwd() + 'app/utils/LoggerMixin.js')(init); // class approach
};
LoggerController.prototype.index = function index(controller) {
controller.logMessage('blah'); // using mixin
Log.logError('hi'); // using class
global.logWarning('yep'); // global approach
return controller.send({success: true});
};
So there are options... just have to find what you think is the best approach.
Every answer I see online either looks complicated, or relies on external libraries. Why not just boil down to the basics, assuming you use a custom type design pattern, which is very similar to traditional OOP.
parent.js
//the main parent class
// class Parent
module.exports = Parent;
function Parent(a) {
if (!(this instanceof Parent)) {
return new Parent(a);
}
this.a = a; //Some parent variable
}
Parent.prototype = {
// Instantiate child:
getChild: function() {
var Child = require('./child');
return new Child(this);
},
// Some parent function, print some text:
printText: function(text) {
console.log(text);
}
};
child.js
//Similar to class Child extends Parent
module.exports = Child;
function Child(parent) {
this.parent = parent;
}
Child.prototype = {
// Prints Parent Variable:
printParentVariable: function() {
console.log(this.parent.a);
},
// Calls Parent Function:
callParentFunction: function() {
this.parent.printText('Child calling parent function.');
}
};
test.js
var parent = require('./parent')('parent text'); //instantiate parent with some text
var child = parent.getChild(); //create instance of a child
//*** Child has full access to its parents variables and methods ***//
console.log(child.parent.a); //Print the parent text "parent text"
child.printParentVariable(); //Child method which prints the parent variable "parent text", identical to line above.
child.parent.printText('Child calling parent'); //Call parent method, to print provided text
child.callParentFunction(); //Calls parent method, identical to above.
Related
I'm want to use my Parent's class methods in my child class.
In classical OOP, you would simply extend your child class to make use of your parents' functionality, is this possible using prototype?
Here is my file structure:
Parent.js
var Parent = function(){
this.add = function(num) {
return num + 1;
};
};
module.exports = Parent;
Child.js
var Parent = require("./parent.js"),
util = require("util");
var Child = function() {
this.sum = function(num) {
// I want to be able to use Parent.add() without instantiating inside the class
// like this:
console.log(add(num));
};
};
util.inherits(Child, Parent);
module.exports = Child;
program.js
var child = require("./child.js");
var Calculator = new child();
Calculator.sum(1);
Obviously, add() is undefined here.
I've tried using util.inherits but it I'm not sure it's the right approach.
I'd also like to ask if this is a good design pattern in JavaScript in general, considering I'd like to have multiple child classes inheriting from my parent?
There are two issues with your code:
First, as mentioned in the comments by #Pointy, the add method in Child.js should be qualified with this.. This is because using add will resolve it to the root scope (window in browsers).
Second, you are binding the add method in Parent to each particular instance independently, by using this.add = function(...){...}. Bind it to the Parent prototype and you'll get what you want.
var Parent = function() {}
Parent.prototype.add = function(num) { return num + 1; }
The function Parent.prototype.add will be inferred to all instances of Parent and its derived objects.
I'm using one of the approaches to class inheritance in JavaScript (as used in the code I'm modifying), but do not understand how to attach additional functionality for a method in a subclass to the functionality the respective parent class method already has; in other words, I want to override a parent's method in the child class with a method that besides its own sub-class-specific stuff does also the same the parent's method is doing. So, I'm trying to call the parent's method from the child's method, but is it even possible?
The code is here: http://jsfiddle.net/7zMnW/. Please, open the development console to see the output.
Code also here:
function MakeAsSubclass (parent, child)
{
child.prototype = new parent; // No constructor arguments possible at this point.
child.prototype.baseClass = parent.prototype.constructor;
child.prototype.constructor = child;
child.prototype.parent = child.prototype; // For the 2nd way of calling MethodB.
}
function Parent (inVar)
{
var parentVar = inVar;
this.MethodA = function () {console.log("Parent's MethodA sees parent's local variable:", parentVar);};
this.MethodB = function () {console.log("Parent's MethodB doesn't see parent's local variable:", parentVar);};
}
function Child (inVar)
{
Child.prototype.baseClass.apply(this, arguments);
this.MethodB = function ()
{
console.log("Child's method start");
Child.prototype.MethodB.apply(this, arguments); // 1st way
this.parent.MethodB.apply(this, arguments); // 2 2nd way
console.log("Child's method end");
};
}
MakeAsSubclass(Parent, Child);
var child = new Child(7);
child.MethodA();
child.MethodB();
No you can't see the parents local variables. You inherit the parents prototype chain, not their local state. In your case you're applying the parent function onto the child object which does not hold the state.
apply(this,...)
means that you're binding the function to the current value of this. when you call method b from the child object, its then bound to the child, and therefore is not operating within the closure that contains the parents value.
I would advice agains using private instance value properties like this because it messes up the prototype. Functions that need to access the private instance variable (each instance has it's own private value) can't be put on the prototype so you can't realy use it.
Here is how your code could work (but I would not do it myself):
var Parent = function(){
var private=22;
this.showPrivate=function(){
console.log(private);
}
}
var Child=function(){Parent.call(this)};
// the following is only usefull if you have functions
// on the parent prototype that don't use privates
Child.prototype=Object.create(Parent.prototype);
// Child.prototype.constructor would now point to Parent
// it's not needed most of the time but you can fix that
Child.prototype.constructor=Child;
var c = new Child();
c.showPrivate();
Here is how you could use "private" functions:
var Parent = function(name){
//public instance variable
this.name=name;
}
Parent.prototype=function(){
// privates on the prototype (shared among instances)
var privateFunction=function(me){
console.log("private function called in:"+me.name);
console.log("shared in "+me.name
+" is now:"+shared+" setting it to 'changed'");
shared="Changed";
}
// private shared value
var shared="Parent"
return{
constructor:Parent,
publicFn:function(){
privateFunction(this);
}
};
}();
var Child=function(name){Parent.call(this,name)};
Child.prototype=Object.create(Parent.prototype);
Child.prototype.constructor=Child;
var c = new Child("child1");
var c2 = new Child("child2");
c.publicFn();
c2.publicFn();//shared is already changed by 'child1'
More info on constructor functions here
The variable var parentVar = inVar; is a local and private variable available only in the Parent() function and visible only to functions defined in the same scope (Parent()).
I think that best way here would be to modify the Parent class in such way that the parentVar wouldn't be private, but public:
function Parent(inVar) {
this.parentVar = inVar;
}
I am using Lightbox2
https://github.com/lokesh/lightbox2/blob/master/js/lightbox.js
And I don't understand why all the inner members of Lightbox are prototyped (Lightbox.prototype.init) and not simply members (Lightbox.init)?
If they are specific to each instance of lightbox wouldn't it be easier to use this.init?
Confused? Don't be...
Think of it this way:
Lightbox is your class definition, but it's not yet an instance.
Whatever you put directly on the class is like a static member:
Lightbox.staticFunc = function() {
// "this" will not point to instance object
};
Whatever you put on its prototype is a shared instance member:
Lightbox.prototype.instanceFunc = function() {
// "this" will point to object instance so members can be accessed
};
When you create an instance of a class, all instance members are accessible throught this keyword, but static ones through class definition:
var someData = Lightbox.staticFunc();
var l = new Lightbox();
l.instanceFunc();
Does this clear you understanding of prototype members?
Lightbox code then
The code that you've been looking at means this:
// this is a constructor that accesses instance properties (using "this")
// ------
// since properties are accessed via "this.something" means that they are
// not shared between instances but are part of one particular instance
// ------
function Lightbox(options) {
this.options = options;
this.album = [];
this.currentImageIndex = void 0;
this.init();
}
// adding an instance method that will be accessible to lightbox object instance
// that's why it can also access instance members (using "this")
// ------
// all functions that are defined on the prototype are shared between
// all instances so they consume less resources because not every
// object instance created them separately.
// ------
Lightbox.prototype.init = function() {
this.enable();
return this.build();
};
But some parts of this code are a bit confusing i.e.
LightboxOptions = (function() {
function LightboxOptions() {
this.fileLoadingImage = 'images/loading.gif';
this.fileCloseImage = 'images/close.png';
this.resizeDuration = 700;
this.fadeDuration = 500;
this.labelImage = "Image";
this.labelOf = "of";
}
return LightboxOptions;
})();
LightboxOptions class is contained within a function closure even though it doesn't define any private data, so the outer immediately executing function could be omitted in this example while having identical results:
LightboxOptions = function() {
this.fileLoadingImage = 'images/loading.gif';
this.fileCloseImage = 'images/close.png';
this.resizeDuration = 700;
this.fadeDuration = 500;
this.labelImage = "Image";
this.labelOf = "of";
};
It would of course be possible to define those functions in a constructor using this but then they wouldn't be shared between instances hence every object instance would define the same function hence consuming more resources. So this is not the same although from the execution point it does look the same:
CustomClass = function() {
this.prop = true;
};
CustomClass.prototype.method = function() { alert("I'm shared."); };
is slightly different than:
CustomClass = function() {
this.prop = true;
this.method = function() { alert("I'm duplicated in every instance."); };
};
The later consumes more resources while function is defined for every object instance.
...and a bit more to completely clear this thing
Suppose we have this class definition:
var C = function() {
this.prop = true;
this.method = function() { console.log("Per instance method"); };
}
C.prototype.method = function() { console.log("Shared instance method"); };
What happens here if we call these lines of code
var a = new C();
var b = new C();
a.method();
b.method();
delete a.method;
a.method();
b.method();
What do you think the output would be? You should get at least a little confused what happens after delete? Which method will get deleted? Per instance? Shared? Both? Well as it should be per instance method gets deleted on object instance a, that's why afterwards it reports that the shared method has been called. But only on a. b still has its own per instance method.
So without any further ado, output looks like this:
Per instance method // a.method
Per instance method // b.method
Shared instance method // a.method
Per instance method // b.method
What about prototype properties
These are different. When you create an object instance all those properties get copied to every object and are not shared. So whatever you do on them within the realm of a particular object will not get reflected to others.
If you'd then delete such property on a particular object it would still be available with its initial value as it was when object got instantiated.
var C = new function() {};
C.prototype.prop = 1;
var a = new C();
var b = new C();
a.prop = 10; // does not change the value of "b.prop"
delete a.prop; // "a.prop" is now back to 1
If they are specific to each instance of lightbox wouldn't it be
easier to use this.init?
They shouldn't be that's why they are putting everything in prototype object. When you use prototype, all methods still become available to you only that they do not become instance members.
JavaScript works with prototype chain, when it sees a method, it searches through the prototype chain till it finds the specified method. This process goes till the final Object object if not found in the middle.
You should only create instance members (via this) that you think are reasonable or needed because it adds an overhead (computational waste) if you put unnecessary methods using this keyword eg instance members.
I'm browsing the discussion for a similar topic, but can't find my situation...
Am trying call parent constructors with parameters... can't seem to get it right.
I have a PhysicsBody superclass that takes aNode as its only constructor argument:
function PhysicsBody(aNode) {
this.userData = aNode;
// ...
}
Of this PhysicsBody inherits a DynamicBody class. Is constructor also takes aNode as only argument... Like I would do it in Java, I'd love to call something equivalent to "super(aNode"); Can't seem to find out how.
Here's the DynamicBody class:
// Wanted to give "new PhysicsBody(this, aNode)", but that fails!
DynamicBody.prototype = new PhysicsBody();
DynamicBody.prototype.constructor=DynamicBody;
function DynamicBody(aNode) {
// calling the parent constructor fails too:
// PhysicsBody.prototype.constructor.call(this, aNode);
//...
}
One way to do it:
function PhysicsBody( aNode ) {
this.userData = aNode;
}
PhysicsBody.prototype.pbMethod = function () {};
function DynamicBody( aNode ) {
PhysicsBody.call( this, aNode );
}
// setting up the inheritance
DynamicBody.prototype = Object.create( PhysicsBody.prototype );
DynamicBody.prototype.dbMethod = function () {};
Now, when you do
var pb = new PhysicsBody( '...' );
the instance pb gets a userData property and also inherits the methods from PhysicsBody.prototype (pbMethod in this case).
When you do
var db = new DynamicBody( '...' );
the instance db gets a userData property and also inherits the methods from DynamicBody.prototype (dbMethod in this case), which in turn inherits from PhysicsBody.prototype.
If I understand you correctly, by saying you want to inherit the parent constructor arguments, you mean that new DynamicBody(1, 2, 3) will internally call PhysicsBody(1, 2, 3) for the DynamicBody instance.
This can be accomplished by using .apply and passing arguments along: http://jsfiddle.net/pmkrQ/.
function DynamicBody() {
PhysicsBody.apply(this, arguments);
}
Basically I want inheritable functions as in
Base = function() { };
Base.prototype.foo = function() {
console.log("base foo");
};
Derived = function() { };
somelib.inherit(Derived, Base);
Derived.prototype.foo = function() {
console.log("derived foo");
}
d = new Derived():
d.foo();
And I want it to print
derived foo
base foo
Yes I know I can explicitly call Base.prototype.foo.call(this); I'm just wondering if there is a pattern for calling overridden super class functions automatically. The problem I'm trying to solve is 2 fold.
derived classes should NOT have to remember to call their parent's method, it just happens automatically.
if 1. can't happen then at least I'd like Derived not to call Base by name since that's brittle. Rather I'd like it call parentclass or something so you don't have to know the base. That way if you change the name of the base you don't have to go fixing every derived class.
You can implement such functionality by using a structure like:
function Base(){}
Base.prototype.destroy = function(){console.log('Base destroy');};
function Derived(){}
Derived.prototype = new Base; // Let Derived inherit from Base
// Override the `destroy` method
Derived.prototype.destroy = function() {
console.log('Derived destroy');
// Call parent class method
this.constructor.prototype.destroy();
// If the context of the method is important, you can use Function.call:
//this.constructor.prototype.destroy.call(this);
};
// Create an instance of Derived, and call the destroy method:
(new Derived).destroy();
I would suggest thinking about exactly why you are doing this, at least in terms of requirement #1. Keep in mind that your desired pattern would take away a great deal of flexibility. For instance, if you have a situation where you want to print the statements in the opposite order:
base foo
derived foo
You would either have to abandon your pattern or create a function foo2() in the derived class which then calls foo() in the base class. Neither is very pretty.
Same goes if you even want to do something as simple as:
derived foo
base foo
one more thing in the derived function
I would contend that using this pattern may work for the exact thing you want to do right now, but may give you fits when you want to make a seemingly trivial change down the road. All to save one line of code!
As far as I know there is no language integrated destructor functionality in JavaScript. It is all about frameworks. If you are using ASP.NET Ajax, for example, the framework would expect that your objects would have a dispose method, responsible for freeing up resources (event handlers). So, it is up to you.
Ok, this isn't quite what you are looking for, in that it's not a "pattern", but it is a potential implementation path you could follow:
Take a look # the MooTools Class.Extras package (for lack of a better word). Using the Chain Class, you could probably get the desired functionality.
var parent = (function () {
var construct = function () {
};
construct.prototype = {
constructor: construct,
destroy: function () {
console.log('parent destruction');
}
}
return construct;
})();
var child = (function (parent) {
var construct = function () {
};
construct.prototype = Object.create(parent.prototype);
construct.prototype.constructor = construct;
construct.prototype.destroy = function () {
parent.prototype.destroy.call(this); // calling parent, too
console.log('child destruction');
};
return construct;
})(parent);
child_instance = new child();
child_instance.destroy();
I would prefer a way where I don't assign Derived = chainify() so that the api would be the same as you had in your question but as of right now this is the best way I can get it to work. It works by replacing each method of the object with a method that calls the replaced method and travels up the parent chain calling their methods along the way.
function chainify() {
return function () {
var property;
for (property in this) {
if (typeof this[property] === "function") {
this[property] = chain(this[property], property);
}
}
function chain(method, method_name) {
return function() {
method();
var current = this;
while (current = current.parent) {
if (current.hasOwnProperty(method_name)) {
current[method_name].apply(this, arguments);
}
}
};
}
}
}
var somelib = function() { };
somelib.inherit = function (derive, base) {
derive.prototype = new base;
derive.prototype.parent = base.prototype;
};
var Base = function() { };
Base.prototype.foo = function() {
console.log("base foo");
};
var Derived = chainify();
somelib.inherit(Derived, Base);
Derived.prototype.foo = function() {
console.log("derived foo");
};
d = new Derived();
d.foo();