I need to create a function in JS that gets all the methods from the whole inheritance tree so as to insert one <button> for each method. I have this code
function A () {
}
A.prototype.a = function () {
console.log('a');
}
function B () {
this.super = A;
this.super();
}
B.prototype = new A;
B.prototype.constructor = B;
B.prototype.b = function () {
console.log('b');
}
function C () {
this.super = B;
this.super();
}
C.prototype = new B;
C.prototype.constructor = C;
C.prototype.c = function () {
console.log('c');
}
function D () {
}
D.prototype = C;
D.prototype.constructor = D;
D.prototype.d = function () {
console.log('d');
}
const dd = new D();
I need some way to find the methods of the whole tree in case I didn't know how many ancestors an object has. For example: If an object C had A and B as its ancestors, I need the methods from A, B, and C; If a D object were a child of A-B-C, I need the methods of them four (A, B, C, and D). I may be able to trace by hand each method so as to write a code that does that for me, buy I need it to be dynamic.
This is what I'm using:
console.log(Object.getOwnPropertyNames(dd.__proto__).filter(function (property) {
return (
typeof dd.__proto__[property] === 'function' && property !== 'constructor'
);
}))
There is a mistake in your setup-code:
Change:
D.prototype = C;
to:
D.prototype = new C;
Then to get the list of methods (even when not enumerable), make a recursive call. You can even make it a generator.
To make clear where the methods come from, I have prefixed them with the name of the prototype object (like A.prototype). You will see that when functions with the same name exist at multiple levels of the prototype chain, they get each listed:
function * iterMethods(o) {
if (!o || o === Object.prototype) return;
for (let name of Object.getOwnPropertyNames(o)) {
try {
if (name !== "constructor" && typeof o[name] === "function") {
yield o.constructor.name + ".prototype." + name;
}
} catch {}
}
yield * iterMethods(Object.getPrototypeOf(o));
}
// Your code:
function A () {
}
A.prototype.a = function () {
console.log('a');
}
function B () {
this.super = A;
this.super();
}
B.prototype = new A;
B.prototype.constructor = B;
B.prototype.b = function () {
console.log('b');
}
function C () {
this.super = B;
this.super();
}
C.prototype = new B;
C.prototype.constructor = C;
C.prototype.c = function () {
console.log('c');
}
function D () {
}
D.prototype = new C;
D.prototype.constructor = D;
D.prototype.d = function () {
console.log('d');
}
const dd = new D();
// The call:
console.log(Array.from(iterMethods(Object.getPrototypeOf(dd))));
It is easier to set up this prototypal hierarchy when you use the class ... extends syntax. I would also not define super as that is a keyword that is natively available. Here is how that would look:
function * iterMethods(o) {
if (!o || o === Object.prototype) return;
for (let name of Object.getOwnPropertyNames(o)) {
try {
if (name !== "constructor" && typeof o[name] === "function") {
yield o.constructor.name + ".prototype." + name;
}
} catch {}
}
yield * iterMethods(Object.getPrototypeOf(o));
}
// class syntax version:
class A {
a() {
console.log('a');
}
}
class B extends A {
b() {
console.log('b');
}
}
class C extends B {
c() {
console.log('c');
}
}
class D extends C {
d() {
console.log('d');
}
}
const dd = new D();
// The call:
console.log(Array.from(iterMethods(Object.getPrototypeOf(dd))));
Suppose there are 2 functions A() and B():
var A = function() {
this.name = 'test'
}
A.prototype.showName() = {
console.log(this.name)
}
var B = function() {
this.age = 10
}
B.prototype.showAge() = {
console.log(this.age)
}
var a = new A();
var b = new B();
what I require is the instance of B() should inherit from instance of A()
Note: instance of B() should still have a function showAge()
please help to run a function that is in a different scope
have the following code:
function a(){
var rrr = 8;
function aim(arg){
console.log('aim' + arg);
console.log(rrr);
}
};
function b(){
a.aim('this is argument');
};
call a.aim ('this is argument'); does not work, the console displays a message
Uncaught ReferenceError: a is not defined
tried to call through apply. also unsuccessfully
using revealing module pattern:
var a = function(){
var rrr = 8;
function aim(arg){
console.log('aim' + arg);
console.log(rrr);
}
return {
aim: aim
}
}();
function b() {
a.aim('test');
}
function a(){
var rrr = 8;
return function aim(arg){
console.log('aim' + arg);
console.log(rrr);
}
};
function b(){
var aim = a();
aim('this is argument');
};
If you want to refer to a function as an object you need to create it first. Also, aim should be a property of this function (class)
function a() {
var rrr = 8;
this.aim = function(arg) {
console.log('aim' + arg);
console.log(rrr);
}
};
function b() {
var aa = new a();
aa.aim('this is argument');
}
You need the 2 minor changes:
function a(){
var rrr = 8;
this.aim = function(arg){
console.log('aim' + arg);
console.log(rrr);
}
};
var aa = new a();
function b(){
aa.aim('this is argument');
};
is this a good pattern for OO JS?
What I am looking for is an easy way to solve inheritance in JavaScript.
function MySuperClass(arg)
{
this.arg1 = arg;
}
function MyBaseClass(arg)
{
this.base = MySuperClass;
this.base(arg);
this.arg2 = arg;
}
MyBaseClass.prototype = new MySuperClass();
function MySpecificClass(arg)
{
this.base = MyBaseClass;
this.base(arg);
this.arg3 = arg;
}
//ensures inheritance of all properties
MySpecificClass.prototype = new MyBaseClass();
var myFirstInstance = new MySpecificClass("test");
var mySecondInstance = new MySpecificClass("test2");
Note: See the end for an ES2015 update.
ES5 and earlier
There are a couple of problems there.
Your MySuperClass function expects an argument, but you can't give it one when you're calling it to create the MyBaseClass.prototype.
The base property you're setting on the instance won't work correctly for the code in MyBaseClass, because MyBaseClass expects that to be MySuperClass, but it isn't, because MySpecificClass has overwritten it.
This is complex stuff. You're very smart being sure to do three generations (MySuperClass, MyBaseClass, and MySpecificClass), because it's really easy to do this for just a two-level hierarchy, but for three+ levels, it's much more complicated. :-)
If you want a thorough discussion of dealing with inheritance, calling into superclass methods, etc., in JavaScript, I've written an article on it, and written a toolkit for doing it. Reading the article and looking at the toolkit source (which goes beyond the article) may be useful in understanding how the prototype chain works and how to work with it.
Here's an example not using any toolkit and not trying to make supercalls easy. To keep things clear, I've used the terms Parent, Child, and GrandChild for the three generations:
// A parent (base) "class"
function Parent(a) {
this.a = a;
}
Parent.prototype.one = function() {
console.log("I'm Parent#one: a = " + this.a);
};
Parent.prototype.two = function() {
console.log("I'm Parent#two: a = " + this.a);
};
// A child "subclass"
function Child(a, b) {
// Chain to "superclass" constructor
Parent.call(this, a);
// Do our own init
this.b = b;
}
// Create the prototype objct that `new Child` will assign to instances
// by creating a blank object backed by `Parent.prototype`. Also set
// the `constructor` property on the object; JavaScript defines that it
// will refer back to the function on the default prototype objects, so
// we do that for consistency despite nothing in JavaScript actually
// _using_ `constructor`.
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
// Add things to `Child.prototype`
Child.prototype.one = function() {
Parent.prototype.one.call(this);
console.log("I'm Child#one: b = " + this.b);
};
Child.prototype.three = function() {
console.log("I'm Child#three: b = " + this.b);
};
// A grandchild "subclass"
function GrandChild(b, c) {
// Chain to "superclass" constructor
// Note that GrandChild has a fixed value for Parent's `a`
Child.call(this, "GrandChildFixedA", b);
// Do our own init
this.c = c;
}
// Again create a blank object to be the prototype `new GrandChild`
// assigns, again set `constructor`
GrandChild.prototype = Object.create(Child.prototype);
GrandChild.prototype.constructor = GrandChild;
// Add things to it
GrandChild.prototype.one = function() {
Child.prototype.one.call(this);
console.log("I'm GrandChild#one: c = " + this.c);
};
GrandChild.prototype.three = function() {
Child.prototype.three.call(this);
console.log("I'm GrandChild#three: c = " + this.c);
};
Usage:
var p = new Parent("ParentA");
console.log("Calling p.one");
p.one(); // "I'm Parent#one: a = ParentA"
console.log("Calling p.two");
p.two(); // "I'm Parent#two: a = ParentA"
var c = new Child("ChildA", "ChildB");
console.log("Calling c.one");
c.one(); // "I'm Parent#one: a = ChildA" then "I'm Child #one: b = ChildB"
console.log("Calling c.two");
c.two(); // "I'm Parent#two: a = ChildA"
console.log("Calling c.three");
c.three(); // "I'm Child#three: b = ChildB"
var gc = new GrandChild("GrandChildB", "GrandChildC");
console.log("Calling gc.one");
gc.one(); // "I'm Parent#one: a = GrandChildFixedA" then "I'm Child #one: b = GrandChildB" then "I'm GrandChild#one: c = GrandChildC"
console.log("Calling gc.two");
gc.two(); // "I'm Parent#two: a = GrandChildA"
console.log("Calling gc.three");
gc.three(); // "I'm Child#three: b = GrandChildB" then "I'm GrandChild#three: c = GrandChildC"
Testing instanceof, although if you're using instanceof a lot, you might want to read up on duck typing:
// Some things that should be true
console.log("p instanceof Parent? " + (p instanceof Parent));
console.log("c instanceof Parent? " + (c instanceof Parent));
console.log("c instanceof Child? " + (c instanceof Child));
console.log("gc instanceof Parent? " + (gc instanceof Parent));
console.log("gc instanceof Child? " + (gc instanceof Child));
console.log("gc instanceof GrandChild? " + (gc instanceof GrandChild));
// And some things that *shouldn't* be true:
console.log("p instanceof Child? (should be false) " + (p instanceof Child));
console.log("p instanceof GrandChild? (should be false) " + (p instanceof GrandChild));
console.log("c instanceof GrandChild? (should be false) " + (c instanceof GrandChild));
If you're not in an ES5-enabled environment, you can use this shim for Object.create (note: not a complete shim, just enough to enable the above):
Object.create = function(p) {
var o;
function ctor() {
}
ctor.prototype = p;
o = new ctor();
ctor.prototype = null;
return o;
};
You can see why a toolkit script makes life a bit easier. You have several to choose from. Here's what the above looks like using Lineage, my toolkit:
// A parent (base) "class"
var Parent = Lineage.define(function(p) {
p.initialize = function(a) {
this.a = a;
};
p.one = function() {
console.log("I'm Parent#one: a = " + this.a);
};
p.two = function() {
console.log("I'm Parent#two: a = " + this.a);
};
});
// A child "subclass"
var Child = Lineage.define(Parent, function(p, pp) {
p.initialize = function(a, b) {
// Chain to "superclass" constructor
pp.initialize.call(this, a);
// Do our own init
this.b = b;
};
p.one = function() {
pp.one.call(this);
console.log("I'm Child#one: b = " + this.b);
};
p.three = function() {
console.log("I'm Child#three: b = " + this.b);
};
});
// A grandchild "subclass"
var GrandChild = Lineage.define(Child, function(p, pp) {
p.initialize = function(b, c) {
// Chain to "superclass" constructor
// Note that GrandChild has a fixed value for Parent's `a`
pp.initialize.call(this, "GrandChildFixedA", b);
// Do our own init
this.c = c;
};
p.one = function() {
pp.one.call(this);
console.log("I'm GrandChild#one: c = " + this.c);
};
p.three = function() {
pp.three.call(this);
console.log("I'm GrandChild#three: c = " + this.c);
};
});
Usage is the same.
ES2015 and later
As of ES2015 (aka "ES6"), JavaScript got the class and super keywords, which dramatically simplify the above, and can be used today with transpiling.
class Parent {
constructor(a) {
this.a = a;
}
one() {
console.log("I'm Parent#one: a = " + this.a);
}
two() {
console.log("I'm Parent#two: a = " + this.a);
}
}
class Child extends Parent {
constructor(a) {
super(a);
}
one() {
super.one();
console.log("I'm Child#one: a = " + this.a);
}
three() {
console.log("I'm Child#three: a = " + this.a);
}
}
class GrandChild extends Child {
constructor(a) {
super(a);
}
one() {
super.one();
console.log("I'm GrandChild#one: a = " + this.a);
}
three() {
super.three();
console.log("I'm GrandChild#three: a = " + this.a);
}
}
// Usage
var p = new Parent("ParentA");
console.log("Calling p.one");
p.one(); // "I'm Parent#one: a = ParentA"
console.log("Calling p.two");
p.two(); // "I'm Parent#two: a = ParentA"
var c = new Child("ChildA", "ChildB");
console.log("Calling c.one");
c.one(); // "I'm Parent#one: a = ChildA" then "I'm Child #one: b = ChildB"
console.log("Calling c.two");
c.two(); // "I'm Parent#two: a = ChildA"
console.log("Calling c.three");
c.three(); // "I'm Child#three: b = ChildB"
var gc = new GrandChild("GrandChildB", "GrandChildC");
console.log("Calling gc.one");
gc.one(); // "I'm Parent#one: a = GrandChildFixedA" then "I'm Child #one: b = GrandChildB" then "I'm GrandChild#one: c = GrandChildC"
console.log("Calling gc.two");
gc.two(); // "I'm Parent#two: a = GrandChildA"
console.log("Calling gc.three");
gc.three(); // "I'm Child#three: b = GrandChildB" then "I'm GrandChild#three: c = GrandChildC"
I'm using this approach:
var func1 = function(parameter1, parameter2) {
// do your stuff here
}
var func2 = function(parameter1, parameter2, parameter3) {
// call the constructor of func1 with actual 'this'
func1.call(this, parameter1, parameter2);
// do your specific task here
}
func2.prototype = func1.prototype;
func2.prototype.constructor = func2;
works fine :)
I am a c++ programmer, Here is a C++ code, how to have similar JS code,
class A {
public:
void sayHello();
};
class B {
public:
A a;
};
main()
{
B b;
b.a.sayHello();
}
// Define class A
function A() {}
A.prototype.sayHello = function() { alert('hello!'); };
// Define class B
function B() { this.a = new A(); }
// Use them
var b = new B();
b.a.sayHello();
The most basic and simplest example:
function A() {
return {
sayHello: function() {
}
}
}
function B() {
return {
a: new A()
}
}
var b = new B();
b.a.sayHello();