1

I have the JavaScript snippet below. Simply put, what am trying to achieve is; A way to check if a parameter passed to a function is an instance of some predetermined classes. I know I can use

if(obj instanceof className){ /* do stuff * / } else{ /* other things */ }
statements but it would be bulky code, especially if I have a bunch of classes to test against. To cut the story short, how can I achieve what am trying to do with the code below? Thanks all.

class A {
    constructor(name) {
        this._name = name;
    }
}
class B {
    constructor(name) {
        this._name = name;
    }
}
class C {
    constructor(name) {
        this._name = name;
    }
}
let allTemplates = ['A', 'B', 'C', 'Object']; //available classes

let a = new A('A class');
let b = new B('B class');
let c = new C('C class');

function seekTemplateOf(obj) {
    /**find if @arg obj is an instance of any
     ** of the classes above or just an object
     **@return string "class that obj is instance of"
     **/
    return allTemplates.find(function(template) {
        return obj instanceof window[template];
        /*Thought that ^^ could do the trick?*/
    });
}
console.log(seekTemplateOf(a));
/*"^^ Uncaught TypeError: Right-hand side of 'instanceof' is not an object"*/
amrro
  • 1,526
  • 17
  • 21
  • 2
    Why a string? Why not `allTemplates = [A, B, C, Object]`? – deceze Feb 05 '18 at 16:00
  • Sort of sounds to me like you want the [`new.target`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new.target) syntax. You should ask about the actual problem instead of your solution. –  Feb 05 '18 at 16:04
  • related: [Create object from string in JavasScript ECMAScript 6](https://stackoverflow.com/q/31776949/1048572) – Bergi Feb 05 '18 at 16:08
  • 1
    @skinny pete dont think so. – Jonas Wilms Feb 05 '18 at 16:08
  • @JonasW.: Why? This question reads like it's trying to solve a specific problem without actual describing that problem. It could very well be that or it could be something else. Point is to describe what is actually needed, because what they perceive to be a good solution often isn't. –  Feb 05 '18 at 16:10
  • @JonasW.: `window.Object === Object; // true` –  Feb 05 '18 at 16:11
  • Oh right, forgot that `class` behaves like `let`. Actually `window.A` fails because automatic global scope was removed in ES6 – Jonas Wilms Feb 05 '18 at 16:13

2 Answers2

1

Change your strings to references:

let allTemplates = [A, B, C, Object];

Then check if the objects constructor is equal to that:

const obj = new A;
const objClass = allTemplates.find(c => obj.constructor === c);

Alternatively ( if some prototype hacker forgot to set constructor) you might get the definite prototype:

const obj = new A;
const objClass = allTemplates.find(c => Object.getPrototypeOf(obj) === c.prototype);

Or you might simply use instanceof then:

const obj = new A;
const objClass = allTemplates.find(c =>  obj instanceof c);
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
1

You could use an object for the templates and check againt the given objects.

class A { constructor(name) { this._name=name; } }
class B { constructor(name) { this._name=name; } }
class C { constructor(name) { this._name=name; } }

let allTemplates = { A, B, C, Object };

let a = new A('A class');
let b = new B('B class');
let c = new C('C class');

function seekTemplateOf(obj) {
    return Object.keys(allTemplates).find(template => obj instanceof allTemplates[template]);
}

console.log(seekTemplateOf(a));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392