0

My object context is not where I expect it to be.

It should be of the class type as thrown, but when caught is object. Why is this so? Probably something stupid. It nearly always is.

I have to use an old unknown JS runtime. It can't be upgraded so I can't use newer features, etc.

I ported the code to run in Node so it's slightly different in terms of imports and exports, but the prototypes and functions are the same. The behavior is also the same: unwanted.

This ClassA provides the test case.

import ClassB from "./ClassB.js"
import ExceptionC from "./ClassB.js"

export default function ClassA() {};

ClassA.prototype = {
    objB: new ClassB(),

    funcA: function() {
        try {
            this.objB.thrower();
        }
        catch (thrownFromB) {
            console.log("Caught Exception. This exception instance should be an ExceptionC. It is type:" + typeof thrownFromB);
            if (thrownFromB instanceof ExceptionC) {
                console.log("ExceptionC message: " + thrownFromB.message + "  origError: " + thrownFromB.origError);
            }
        }
    }
};

This ClassB provides the throw and the custom exception class also.

export default function ClassB() {};

ClassB.prototype = {
    AugmentedException: function(errorMsg, origError) {
        Error.call(this);
        this.message = errorMsg;
        this.origError = origError;
    },

    ExceptionC: function(errorMsg, origError) {
        AugmentedException.call(this, errorMsg, origError);
    },

    thrower: function() {
        console.log("throwing a new ExceptionC");
        throw new ExceptionC("foo", "bar");
    }
};

This is the main function.

import ClassA from "./ClassA.js"

var foo = new ClassA();
foo.funcA();

This is the output.

>> OUTPUT:
>> throwing a new ExceptionC...
>> Caught Exception. This exception instance should be an ExceptionC. It is type: object
SPB
  • 146
  • 2
  • 10
  • 1
    `import ExceptionC from "./ClassB.js"` - that's not how imports work. You're essentially importing `ClassB` (the default export) under the alias `ExceptionC`. Confirm with `console.log(ClassB === ExceptionC)`. – Bergi Aug 23 '21 at 23:10
  • 1
    Neither `AugmentedException` nor `ExceptionC` should be on the prototype object of anything. You're also not referencing them properly. Given the the vague description "*losing context*", I suspect you don't understand the [difference between variables and properties](https://stackoverflow.com/q/13418669/1048572?javascript-do-i-need-to-put-this-var-for-every-variable-in-an-object)? – Bergi Aug 23 '21 at 23:12

1 Answers1

2

Some issues I can suspect:

  1. In ClassB.js you use some undefined variables. Due to this, ReferenceError is thrown instead of ExceptionC. So in these lines:

    AugmentedException.call(this, errorMsg, origError);
    // ...
    throw new ExceptionC("foo", "bar");
    

    you possibly mean this:

    ClassB.prototype.AugmentedException.call(this, errorMsg, origError);
    // ...
    throw new ClassB.prototype.ExceptionC("foo", "bar");
    
  2. In ClassA.js you import the same exported default class into 2 different variables. Due to this, in ExceptionC you actually have the same ClassB. So in this line:

    import ExceptionC from "./ClassB.js"
    

    you possibly mean this:

    const ExceptionC = ClassB.prototype.ExceptionC;
    

With these changes, I get expected:

throwing a new ExceptionC
Caught Exception. This exception instance should be an ExceptionC. It is type:object
ExceptionC message: foo  origError: bar
vsemozhebuty
  • 12,992
  • 1
  • 26
  • 26
  • Thanks. I made those changes but I still don't pass the condition: ```thrownFromB instanceof ExceptionC```, it seems because ```thrownFromB``` is an ```object```, instead of an ```ExceptionC```. – SPB Aug 23 '21 at 23:48
  • 1
    @SPB Try to add `console.log(thrownFromB)` in `catch` block to be sure you catch the expected error. – vsemozhebuty Aug 23 '21 at 23:52
  • 1
    Ah, yes it's ```ReferenceError: ExceptionC``` is not defined. Have to use ```this.ExceptionC``` in the ```thrower()``` – SPB Aug 23 '21 at 23:57
  • So, it now essentially works but I'm confused as to why the ```typeof``` is ```object```? – SPB Aug 24 '21 at 00:00
  • 1
    `typeof` has very limited set of types: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof#description . For any error it returns `'object'`. – vsemozhebuty Aug 24 '21 at 00:05
  • Understood after reading: ``typeof is a construct that "returns" the primitive type of whatever you pass it.`` here: https://stackoverflow.com/questions/14839656/differences-between-typeof-and-instanceof-in-javascript Confusing behaviour for me as I can't think of another language that I've used that does this. – SPB Aug 24 '21 at 00:06
  • ```primitiveof``` would be better. – SPB Aug 24 '21 at 00:06
  • 1
    Thanks @vsemozhebuty I appreciate the solution! – SPB Aug 24 '21 at 00:08
  • 1
    @SPB Maybe you want https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor instead. – vsemozhebuty Aug 24 '21 at 00:10
  • 1
    @SPB I.e. try: `"It is type:" + thrownFromB.constructor.name` – vsemozhebuty Aug 24 '21 at 00:15