JS Inheritance example: too much recursion - javascript

Sorry for dump question I am new to js. I would like to override f2() function in D "class". But for some reason Fire Fox told me: "too much recursion". Could you please point me where recursion happening and how to make this code work as expected?
var B = function () {
};
B.prototype.f2 = function (x) {
return 2 * x;
};
var C = function () {
B.call(this);
};
var D = function () {
C.call(this);
};
D.prototype.f2 = function (x) {
return C.prototype.f2.call(this, x) * 7;
};
inherit(B, C);
inherit(C, D);
function inherit(Child, Parent) {
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
}
var d = new D();
console.log(d.f2(3));

Two problems:
You need to set up the XYZ.prototype objects before you try to add properties to them. Since your inherit function creates them, you must ensure that you do things in the right order.
You have the order of the parent and child backward in your inherit calls. It's inherit(child, parent), not inherit(parent, child).
var B = function () {
};
B.prototype.f2 = function (x) {
return 2 * x;
};
var C = function () {
B.call(this);
};
inherit(C, B); // *** Moved and updated
var D = function () {
C.call(this);
};
inherit(D, C); // *** Moved and updated
D.prototype.f2 = function (x) {
return C.prototype.f2.call(this, x) * 7;
};
function inherit(Child, Parent) {
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
}
var d = new D();
console.log(d.f2(3));
The ES2015 version, for comparison:
class B {
f2(x) {
return 2 * x;
}
}
class C extends B {
}
class D extends C {
f2(x) {
return super.f2(x) * 7;
}
}
const d = new D();
console.log(d.f2(3));

Related

Use Arrow Function in Class Method to access Class Property

I've put together a simplified example of what I'm trying to do, obviously a bit contrived... I have this class:
export class myClass {
a = 'bar';
b = 0;
save(x: any = null): void {
//save all properties
//...
}
}
In other classes that need to use it, I will define foo = new myClass();
Then it can be used either as:
this.foo.b = 3
this.foo.save();
or, because sometimes I just want it on one line (hence the x: any = null:
this.foo.save(this.foo.b = 3);
I would like to write the single line version more elegantly, and feel something like this should be possible... is it?
//How can I make this possible?
this.foo.save(c => c.b = 3)
if it is possible, what would the add method look like?
Many thanks!
Answer for the original question.
If you want this.calc.add(c => c.b = 3), then you need to handle invoking the function c => c.b = 3 once passed to the add method.
So just check the value is a function, if it is then pass this to the function, which would be c in your function, then the return value you add with this.b
Plain old js.
class Calculator {
constructor() {
this.a = 10
this.b = 0
this.sum = 0
}
add(x) {
this.sum = this.a + (typeof x === 'function' ? x(this) : x)
}
}
const calc = new Calculator()
calc.add(c => c.b = 3)
console.log(calc.sum)
calc.add(1)
console.log(calc.sum)
Implicitly assigning is anti pattern
// Something that you should avoid
this.calc.b = 3
class Calc {
constructor(private a: number = 0, private b: number = 0) {}
setA(a: number) {
this.a = a;
return this;
}
setB(b: number) {
this.b = b;
return this;
}
sum() {
return this.a + this.b;
}
}
const calc = new Calc();
// will return 0
console.log(calc.sum());
// will return 6
console.log(calc.setA(1).setB(5).sum());
const calc1 = new Calc(1,2);
// will return 3
console.log(calc1.sum());

Limit number of times a Class can be instantiated

The following question was asked in a JavaScript interview.
After creating 3 instances of a class, how to prevent further instance creation?
What is the answer for this?
I'm assuming the question requires that you get "clever" and not use any globals nor other classes.
You can use a static method to keep track of created instances. From then on you can throw errors in the constructor to prevent instantiation.
class Foo {
constructor(name) {
if (Foo.maxInstancesReached())
throw 'Max instances reached'
this.name = name
}
static maxInstancesReached() {
if (!this.numOfCreatedInstances)
this.numOfCreatedInstances = 0
return ++this.numOfCreatedInstances > 3
}
}
const foo1 = new Foo('Jack')
const foo2 = new Foo('John')
const foo3 = new Foo('Mary')
const foo4 = new Foo('Rebecca')
This could be achieved through the use of a factory function:
class Special {
}
let specialObjectCounter = 0;
function createSpecial() {
// factory function
if (specialObjectCounter === 3) return;
specialObjectCounter++;
return new Special();
}
const a = createSpecial();
const b = createSpecial();
const c = createSpecial();
const d = createSpecial();
const e = createSpecial();
console.log(a, b, c, d, e);
A more generic version would look like this:
function instanceLimiter(proto, count, action=()=>undefined) {
let counter = 0;
return function(...args) {
if (counter >= count) return action();
counter++;
return new proto(...args);
}
}
// Demo
class Special {
}
const createSpecial = instanceLimiter(Special, 3);
const res = Array.apply(null, Array(5)).map(createSpecial);
console.log(...res);
If you prefer throwing instead of returning undefined you can just pass a different action to instanceLimiter:
instanceLimiter(Special, 3, () => {throw 'Maximum instance count reached'});
Created a static variable and increment the count each time a new instance is created. If the count reaches the threshold, throw an error.
var Foo = function() {
if (Foo.instances >= 3) {
throw new Error("Max number of instances reached");
}
Foo.instances++;
};
Foo.instances = 0;
var a = new Foo();
console.log(a);
var b = new Foo();
console.log(b);
var c = new Foo();
console.log(c);
console.log(Foo.instances);
var d = new Foo();
console.log(d);

Is there something wrong with this following singleton pattern?

I come across singleton pattern, it's quite tricky to understand how to implement it, and I know some people would suggest to avoid it most of the time, so below is specific singleton variation that I find it easy to understand, but somehow I feel that this is not the best implementation of this pattern, can you guys suggest better form of this pattern.
var Foo = (function () {
var instance;
var _priVar = 2;
var log = function() {
console.log("Hello");
};
function Singleton(x, y) {
if (instance) {
return instance;
}
this.name = x;
this.age = y + _priVar;
this.log = log;
instance = this;
}
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
and my goal is that when we do following
var a = new Foo("Bob", 24);
var b = new Foo();
var c = Foo();
var d = Foo.getInstance();
we will still get
a == b // true
a == c // true
a == d // true
a.name // 'Bob'
b.age // 26
c.log // 'Hello'
d.name // 'Bob'
The simplest singleton, also known as module pattern, consists of an object literal:
var foo = (function () {
var x = "Bob",
y = 24,
_priVar = 2;
function log() {
console.log("Hello");
}
return {
name: x,
age: y + _priVar,
log: log
};
}());
If you want to introduce lazy initialisation, you can use an extra getInstance function like in your implementation:
var getFoo = (function () {
var instance = null;
return function getFooInstance() {
if (instance) return instance;
var x = "Bob",
y = 24,
_priVar = 2;
function log() {
console.log("Hello");
}
return instance = {
name: x,
age: y + _priVar,
log: log
};
};
}());
A singleton should never use a constructor like in your code, that's just unnecessary. If you feel a need to pass arguments for initialisation, don't make it a singleton.

Calling a super function from a subclass function [duplicate]

This question already has answers here:
Javascript Class Inheritance For Functions
(2 answers)
Closed 7 years ago.
I am looking to call a superclass function within a subclass function that overrode the superclass function. For Example:
var a = function(x) {
this.val = x || 0;
};
a.prototype.print = function() {
console.log("Class A");
};
var b = function(x, y) {
this.y = y || 0;
a.call(this, x);
};
b.prototype = Object.create(a.prototype);
b.prototype.constructor = b;
b.prototype.print = function() {
console.log("b inherits from ");
// call to superclass print function (a.print)
};
How would I call the superclass print function from the subclass when the subclass already overwrote the superclass function?
You can use superclass.prototype.method.call(argThis, parameters). In your case without parameters will be a.prototype.print.call(this);
So, your code would be
var a = function(x) {
this.val = x || 0;
};
a.prototype.print = function() {
console.log("Class A");
};
var b = function(x, y) {
this.y = y || 0;
a.call(this, x);
};
b.prototype = Object.create(a.prototype);
b.prototype.constructor = b;
b.prototype.print = function() {
console.log("b inherits from ");
a.prototype.print.call(this);
};

How to supplement object function from outside

var object = {}; //lots of stuff in here
var func = object.dosome;
object.dosome = function(a,b) {
func(a,b);
//someth else here i need to add
}
This works but ugly.
So is there a way to supplement object.dosome method, without creating a new variable containing it's function?
Some sort of parent.dosome?
maybe create a class Object and define in its protoype the dosome() method.
var Object = new function() {}; //lots of stuff in here
Object.prototype.dosome = function(a,b) {
func(a,b);
}
//and then
var myObject = new Object();
I think you should read a little about JS OOP. ES6 adds some nice syntactic sugar that can help you achieve what you want in fewer lines of code. Read more here.
However, if you don't want to have problems with the prototype chains, here's a simpler way of achieving what you want:
function chain (baseFunc, func) {
return function () {
var args = [].slice.call(arguments, 0);
args.unshift(baseFunc);
return func.apply(this, args);
};
}
Usage:
var obj = {
doSome: function (a, b) { return a + b; }
};
obj.doSome(4, 5); // 9
obj.doSome = chain(obj.doSome, function (baseFunc, a, b) {
var result = baseFunc(a, b);
return result + 10;
});
obj.doSome(4, 5); // 19
You can go one step further and get rid of the assignment:
function extend (instance, method, func) {
instance[method] = chain(instance[method], func);
}
extend(obj, "doSome", function (baseFunc, a, b) {
var result = baseFunc(a, b);
return result + 2;
});
obj.doSome(4, 5); // 21

Categories