I know there are tons of ways of doing JS inheritance. I am trying to do something here, where I am passing in rows into my sub class, and i want to pass it through to the super class at constructor time :
function AbstractTableModel(rows) {
this.showRows = function() {
alert('rows ' + this.rows);
}
}
function SolutionTableModel(rows) {
this.prototype = new AbstractTableModel(rows);
this.show = function() {
this.protoype.showRows();
};
}
var stm = new SolutionTableModel(3);
stm.show();
fiddle :
http://jsfiddle.net/YuqPX/2/
It doesnt seem to work because the prototype methods are not flowing down :( Any ideas?
Live Demo
First you must define this.rows
function AbstractTableModel(rows) {
this.rows = rows;
this.showRows = function() {
alert('rows ' + this.rows);
};
}
Second, if you want to inherit from AbstractTableModel you ought to do so...
function SolutionTableModel(rows) {
AbstractTableModel.call(this, rows);
this.show = function() {
this.showRows();
};
}
SolutionTableModel.prototype = new AbstractTableModel();
var stm = new SolutionTableModel(3);
stm.show();
/==============================================================================/
Also you can use Parasitic Combination Inheritance Pattern, if you want to avoid calling base constructor twice:
function inheritPrototype(subType, superType) {
var prototype = Object.create(superType.prototype, {
constructor: {
value: subType,
enumerable: true
}
});
subType.prototype = prototype;
}
function AbstractTableModel(rows) {
this.rows = rows;
this.showRows = function () {
alert('rows ' + this.rows);
};
}
function SolutionTableModel(rows) {
AbstractTableModel.call(this, rows);
this.show = function () {
this.showRows();
};
}
inheritPrototype(AbstractTableModel, SolutionTableModel);
var stm = new SolutionTableModel(3);
stm.show();
function AbstractTableModel(rows) {
this.rows = rows;
this.showRows = function() {
alert('rows ' + this.rows);
}
}
function SolutionTableModel(rows) {
var soln = Object.create(new AbstractTableModel(rows));
soln.show = function() {
this.showRows();
};
return soln;
}
var solution = new SolutionTableModel(5);
solution.show();
This is one way of doing the object inheritance. This method is most elegant in my opinion and can be found in detail here
Fiddle
function AbstractTableModel(rows) {
this.rows = rows;
}
AbstractTableModel.prototype.showRows = function() {
console.log('rows ' + this.rows);
}
function SolutionTableModel(rows) {
AbstractTableModel.call(this, rows);
this.show = function() {
this.showRows();
};
}
SolutionTableModel.prototype = Object.create(AbstractTableModel.prototype);
var stm = new SolutionTableModel(3);
stm.show();
here is a working example based on what you have done DEMO:
function AbstractTableModel(rows) {
this.showRows = function () {
alert('rows ' + rows);
}
}
function SolutionTableModel(rows) {
var self = this;
this.prototype = new AbstractTableModel(rows);
this.show = function () {
self.prototype.showRows();
};
}
var stm = new SolutionTableModel(3);
stm.show();
In your class AbstractTableModel there is no this.rows just use rows directly.
The same catch in the second class SolutionTableModel. I prefer to define variable self that points to the created instance of the object.
You miss type protoype it should be prototype
Related
function Singer(g) {
this.genre = g;
this.rock = function() {
console.log("ROCK");
}
}
Singer.prototype.sing = function() {
console.log(this.genre);
}
function metalSinger() {
}
metalSinger.prototype = Singer.prototype
var james = new metalSinger();
console.log(james.sing())
The metalSinger object only inherits the prototype function of object Singer. How can I inherit the variables of Singer (this.genre) and also the function (this.rock) ?
You can use the class pattern with inheritance.
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance
function Singer(g) {
this.genre = g;
this.rock = function() {
console.log("ROCK");
}
}
Singer.prototype.sing = function() {
console.log(this.genre);
}
function MetalSinger(g) {
Singer.call(this, g);
}
var ms = new MetalSinger("foo");
console.log(ms.rock());
One way you can achieve this is by calling the parent constructor function inside the child constructor like this:
function Singer(g) {
this.genre = g;
this.rock = function() {
console.log("ROCK");
}
}
Singer.prototype.sing = function() {
console.log(this.genre);
}
function metalSinger() {
Singer.call(this, 'metal');
}
metalSinger.prototype = Object.create(Singer.prototype);
var james = new metalSinger();
james.sing();
This way before constructing the child object, parent constructor will be called first to initialise the object.
How can I inherit the variables of Singer (this.genre) and also the function (this.rock) ?
Basically like this:
Singer.call(this, genre);
By doing so, you first call Singer in context of metalSinger which adds its (Singer's) properties to this object of metalSinger. Also it is better to create new object through Object.create() and put all the functions in Prototype.
function Singer(g) {
this.genre = g;
}
Singer.prototype.sing = function() {
console.log(this.genre);
}
Singer.prototype.rock = function() {
console.log("ROCK");
}
function metalSinger(g) {
Singer.call(this, g);
}
metalSinger.prototype = Object.create(Singer.prototype);
var james = new metalSinger("metal");
james.sing(); // "metal"
james.rock(); // "ROCK"
So i have this code:
function Class1() {
this.i = 1;
var that=this;
function nn() {
return 21;
}
this.aa = function() {
nn();
};
this.bb = function() {
this.aa();
};
this.cc = function() {
this.bb();
};
}
var o = new Class1();
var b=o.cc();
alert(b); //undefined
But when the alert is fired, I get an undefined error and not 21, Does the private method can not use a return? Thanks!
When using the function() {} syntax to define a function, you always explicitly need to return the value, i.e. not only from nn, but from all intermediate functions as well.
function Class1() {
this.i = 1;
var that = this;
function nn() {
return 21;
}
this.aa = function() {
return nn();
}
this.bb = function() {
return this.aa();
}
this.cc = function() {
return this.bb();
}
}
var o = new Class1();
var b = o.cc();
alert(b); // "21"
Apart from the answer above, the 'this' context seems weird in your functions. Maybe you are better of with arrow functions if you dont want to bind the this context to each function. I also think that it is better to actually separate private and public functions when using a 'class' like this.
function Class1() {
var _nn = function () {
return 21;
}
var _aa = function () {
return _nn();
}
var _bb = function () {
return _aa();
}
var cc = function () {
return _bb();
};
return {
cc
};
}
var o = new Class1();
var a = o.cc();
console.log(a);
Much easier to understand that it is only cc that is a public function.
So with arrow function it would instead look like this, and you can use the Class1 this context inside of your private functions without doing
var that = this; or using bind.
function Class1() {
this.privateThing = 'private';
var _nn = () => { return this.privateThing; };
var _aa = () => { return _nn(); };
var _bb = () => { return _aa(); };
var cc = () => { return _bb(); };
return {
cc
};
}
I have a name of a private function in JavaScript as a string, how do I call that function?
var test = function () {
this.callFunction = function(index) {
return this["func" + index]();
}
function func1() { }
function func2() { }
...
function funcN() { }
}
var obj = new test();
obj.callFunction(1);
func1 and friends are local variables, not members of the object. You can't call them like that (at least not in any sane way).
Define them with function expressions (instead of function declarations) and store them in an array.
var test = function () {
this.callFunction = function(index) {
return funcs[index]();
}
var funcs = [
function () {},
function () {},
function () {}
];
}
var obj = new test();
obj.callFunction(0);
As your code stands, the functions are not present as properties of the instance. What you need to do is create them as properties of the context.
var test = function () {
this.callFunction = function(index) {
return this["func" + index];
}
this.func1 = function() { }
this.func2 = function() { }
...
}
var obj = new test();
obj.callFunction(1)();
you can use eval
var test = function () {
this.callFunction = function(index) {
return eval("func" + index + '()');
}
function func1() {
return 1;
}
function func2() {
return 2;
}
function funcN() { }
};
var obj = new test();
obj.callFunction(2);
eval is evil
You can use a private array of functions:
var test = function() {
var func = [
function() { return "one" },
function() { return "two"; }
]
this.callFunction = function(index) {
return func[index]();
}
}
var obj = new test();
var ret = obj.callFunction(1);
console.log(ret);
http://jsfiddle.net/V8FaJ/
function condition(){
this.expression = "";
this.toString = function(){
return this.expression;
}
};
function and(first, second){
this.expression = first + " and " + second;
}
function nop(){};
nop.prototype = condition.prototype;
and.prototype = new nop();
var a =new and(1,2);
console.log(a.toString());
it is expected to see "1 and 2" as output but this is what happened:
"[object Object]"
You are transfering the prototype of condition to nop's prototype. The problem is that your condition.toString is not declared in the prototype... Here:
function condition(){
this.expression = "";
};
condition.prototype.toString = function(){
return this.expression;
}
function and(first, second){
this.expression = first + " and " + second;
}
function nop(){};
nop.prototype = condition.prototype;
and.prototype = new nop();
var a =new and(1,2);
console.log(a.toString());
OR
function condition(){
this.expression = "";
this.toString = function(){
return this.expression;
}
};
function and(first, second){
this.expression = first + " and " + second;
}
function nop(){};
nop = condition;
and.prototype = new nop();
var a =new and(1,2);
console.log(a.toString());
you aren't overriding the toString method, because the constructer of condition is never called! try doing this;
condition.prototype.toString=function(){
return this.expression;
}
try passing strings into your and function, as at the moment you are trying to concatenate integers to a string var a =new and("1","2");
it should be like this
function condition(){
this.expression = "";
};
condition.prototype.toString = function(){
return this.expression;
}
Ok, so the problem here is you are mixing two inheritance patterns (http://davidshariff.com/blog/javascript-inheritance-patterns/) the pseudo-classical with the functional patterns.
You can create an object by adding methods on the constructor function:
function MyClass() {
var privateProperty = 1;
this.publicProperty = 2;
function pivateMethod() {
// some code ...
}
this.publicMethod = function() {
// some code ...
};
}
// inheritance
function SubClass() {
MyClass.call(this);
this.newMethod = function() { };
}
Here when you create a instance of this class you are creating every method again.
Then you have the prototype pattern:
function MyClass() {
this._protectedProperty = 1;
this.publicProperty = 2;
}
MyClass.prototype._protectedMethod = function() {
// some code ...
};
MyClass.prototype.publicMethod = function() {
// some code ...
};
// inheritance
function SubClass() {
MyClass.call(this);
}
SubClass.prototype = new MyClass();
SubClass.prototype.newMethod = function() { };
// OR
function SubClass() {
MyClass.call(this);
}
function dummy() { }
dummy.prototype = MyClass.prototype;
SubClass.prototype = new dummy();
SubClass.prototype.newMethod = function() { };
Yhen you must choose one of those two patterns, not both·
I've fixed your code on this fiddle: http://jsfiddle.net/dz6Ch/
Can I call public method from within private one:
var myObject = function() {
var p = 'private var';
function private_method1() {
// can I call public method "public_method1" from this(private_method1) one and if yes HOW?
}
return {
public_method1: function() {
// do stuff here
}
};
} ();
do something like:
var myObject = function() {
var p = 'private var';
function private_method1() {
public.public_method1()
}
var public = {
public_method1: function() {
alert('do stuff')
},
public_method2: function() {
private_method1()
}
};
return public;
} ();
//...
myObject.public_method2()
Why not do this as something you can instantiate?
function Whatever()
{
var p = 'private var';
var self = this;
function private_method1()
{
// I can read the public method
self.public_method1();
}
this.public_method1 = function()
{
// And both test() I can read the private members
alert( p );
}
this.test = function()
{
private_method1();
}
}
var myObject = new Whatever();
myObject.test();
public_method1 is not a public method. It is a method on an anonymous object that is constructed entirely within the return statement of your constructor function.
If you want to call it, why not structure the object like this:
var myObject = function() {
var p...
function private_method() {
another_object.public_method1()
}
var another_object = {
public_method1: function() {
....
}
}
return another_object;
}() ;
Is this approach not a advisable one? I am not sure though
var klass = function(){
var privateMethod = function(){
this.publicMethod1();
}.bind(this);
this.publicMethod1 = function(){
console.log("public method called through private method");
}
this.publicMethod2 = function(){
privateMethod();
}
}
var klassObj = new klass();
klassObj.publicMethod2();
Do not know direct answer, but following should work.
var myObject = function()
{
var p = 'private var';
function private_method1() {
_public_method1()
}
var _public_method1 = function() {
// do stuff here
}
return {
public_method1: _public_method1
};
} ();