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.
Related
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.
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 new to pseudo classes and prototypes in JavaScript and I am having a bit of difficulty implementing it properly. What I am trying to do is have a base 'class' with some fields then create a prototype of that base class with my methods defined as object literals. I am torn between doing it this way and just using singletons inside my base class for my methods. I think though that doing it this way is a little more elegant and I think I am actually not creating every method every time I create a new object.
Anyways, the small issue I am having is referencing the fields of my base class in my methods. Because when I try to reference them as this.field this is referring to the current function/ scope but I want it to reference the newly create object. Is there a work around for this or should I change the way I am creating my methods.
Below is some code that I think will make it more clear what I am doing and the problem I am having.
function BaseClass() {
this.items[];
this.fieldOne = "asdasd";
}
BaseClass.prototype = {
methodOne: function (input) {
function addElement(a. b) {
var element = {};
element.prop1 = a;
element.prop2 = b;
//The issue I am having is that items is undefined, how can I refernce the parent class object.
this.items.push(element);
}
function traverse() {
//go through a list and add a bunch of elements
addElement("ASdasd", 324);
}
},
methodTwo: function () {
//see now fieldOne is asdasd
console.log("fieldOne" + fieldOne);
}
}
var forTest = new BaseClass();
forTest.methodTwo();
So yeah I want to have some fields in the parent class that I can access from any method, but I would rather not just put the functions in my base class so that I do not create every method everytime I create a new object from BaseClass. Is there a work around or a better way to implement this?
Thanks in advance for the help.
You're losing the reference to this inside your nested functions. You can solve that with:
methodOne: function (input) {
var self = this;
function addElement(a. b) {
var element = {};
element.prop1 = a;
element.prop2 = b;
//The issue I am having is that items is undefined, how can I refernce the parent class object.
self.items.push(element);
}
function traverse() {
//go through a list and add a bunch of elements
addElement("ASdasd", 324);
}
// You never called anything?
// is traverse() what you wanted?
traverse();
},
methodOne: function (input) {
function addElement(a. b) {
var element = {};
element.prop1 = a;
element.prop2 = b;
//The issue I am having is that items is undefined, how can I refernce the parent class object.
this.items.push(element);
}
The issue here is that you've encountered javascript design error which is that this in subfunction is bound to wrong object. The ususal workaround for this looks like:
methodOne: function (input) {
var that = this;
function addElement(a, b) {
...
that.items.push(element);
}
}
In fact it's bound to the global object:
var o = {
f : function(){
var g = function(){
this.name = "test";
};
g();
}
};
o.f();
console.log(name); // "test"
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();
In Javascript, I would like to define a class with an inner (or nested) class. Within the inner class I'd like to be able to get access to the parent instance. How can I do this efficiently?
Some code will show what I mean. Suppose I define a class, MyType1, which exposes several properties and one function, SayHello:
(function(){
MyType1 = function(name){
this.TypeName = "MyType1";
this.Name = name;
};
MyType1.prototype.SayHello = function() {
say(this.Name + " says hello...");
};
})();
Ok, now, starting from there, I want to add an "inner class" to MyType1, so I add some new code so that it looks like this:
(function(){
MyType1 = function(name){
this.TypeName = "MyType1";
this.Name = name;
var parentName = name;
this.Child = function(name) {
this.Description = parentName + "'s child, " + name;
};
this.Child.prototype.Introduce = function() {
say(this.Description + ", greets you...");
};
};
MyType1.prototype.SayHello = function() {
say(this.Name + " says hello...");
};
})();
Now I can use these classes like this:
var x = new MyType1("Victor");
x.SayHello();
var c = new x.Child("Elizabeth");
c.Introduce();
that all works. But it defines a new Child function (or type, if you like) for every instance of MyType1. What I'd like to do is get access to the parent class scope, without resorting to that inefficiency.
Something like this:
(function(){
MyType2 = function(name){
this.TypeName = "MyType2";
this.Name = name;
this.Prop1 = 1872;
var parentName = name;
};
MyType2.prototype.SayHello = function() {
say(this.Name + " says hello...");
};
var c1 = function(name) {
this.Description = parentName + "'s child, " + name;
// ^^ no go! ^^
};
c1.prototype.Introduce = function() {
say(this.Description + ", greets you...");
};
MyType2.prototype.Child = c1;
})();
But, this doesn't work. The parentName var is out of scope, of course.
Is there an efficient way for the Child instance (in the constructor, or in any class function) to gain access to the parent (MyType2) instance?
I know that I could define the Child class to be an independent, non-nested class, then in the ctor for that, just pass the Parent instance. But this creates N references to the parent instance, one for every Child instance. That seems like an inefficiency I'd like to avoid.
thanks for any tips.
EDIT - the reason I want the Child to have access to the parent instance, is that the parent holds an object that is fairly expensive to create - something like a db connection - and I'd like the child to be able to utilize that thing.
It would probably help you out if you do away with notions like "type", "class", etc. when dealing with javascript. In javascript, there is no differentiation from "type", "class", "function", "instance", or "object" -- it's "object" all the way down.
Since every "type" is an "object" and is mutable, you get nothing of the sort of strong-typed efficiency gains you might get from Java or C++ by reusing a single type definition. Think of the "new" operator in javascript as something like "clone the definition and call the constructor", after which the definition of the instance could still be changed.
So go with your first, working example: you won't get any gains by doing something different.
This is what I came up after many hours:
var Parent = function() {
this.name = "Parent";
this.Child = Child;
this.Child.prototype.parent = this;
}
var Child = function() {
}
var parent = new Parent();
var child = new parent.Child();
console.log(child.parent.name);
This way you can instantiate as many Parents as you want, with their Childs
underneath, and every Child instance will have access to it's parent instance
through the variable parent.
The only way I can think of is to pass in the parent object to the Child constructor:
MyType2.Child = function (parent, name) {
this.parent = parent;
this.name = name;
this.Description = this.parent.name + "'s child, " + name;
};
And instantiate it with:
var x = new MyType2("Victor");
var c = new MyType2.Child(x, "Elizabeth");
My justification is that it makes more sense that the Child constructor is a "static" property of MyType2, instead of the instantiated object x in your example, since we are talking about types here, which are the same across all instances of MyType2.
I haven't tested this, but you should be able to use JSON for this:
//code here
var number = {
real : {
value : 0, //default value
rational : {
integer : {
isNegative : false,
value : 0 //default value
}
}
},
imaginary : {
//code
}
};
var number2 = Object.create(number.rational.integer.prototype);
Now there may be many issues with this, functional or stylistic. But it is an alternative from the other approaches posted here.
This is one way to do it. This declares an inner object - which is kinda like declaring an inner class and immediately getting an instance of it. A reference to the outer class is simply added as a object attribute in the declaration.
// ES6 - example of an inner object.
class DancingFoo {
constructor(radio) {
this._radioListener = {
outer: this,
onIsPlaying() { this.outer._dancing = true; },
onStoppedPlaying() { this.outer._dancing = false; }
}
radio.attachListener(this._radioListener);
}
}
or if you want an inner class you can create instances of later...
// ES6 inner class example
class DancingFoo {
constructor(radio) {
let RadioListener = class {
constructor(outer) { this.outer = outer; }
onIsPlaying() { this.outer._dancing = true; }
onStoppedPlaying() { this.outer._dancing = false; }
}
radio.attachListener(new RadioListener(this));
}
}