-1

I have a (very) complicated JS class, which has potentially endless nested versions of the same class (and others) under a properties key. It has functions on it which can change features of the properties, eg re-case them, omit or pick some, etc. All of these functions are designed to be non-mutative, returning a new class with new properties.

At any rate, I've run into a SUPER weird issue with an instance of this class. Essentially, the properties accessed from "the outside" are different from those on the inside. (This is after calling snakeCase() to snake case the keys of the properties, but that shouldn't really be relevant to this question, because the problem seems more fundamental/weird than anything specific to this class.

Here's what's going on. I added a testFunc function to debug this issue:

  testFunc = self => {
    const keys = Object.keys(this.properties);
    console.log("KEYS", keys);
    debugger;
    const keys2 = Object.keys(self.properties);
    console.log("KEYS2", keys2);
  };

Here's what I'm calling:

      // SomeSchema is an instance of this class, as is snaked, because snakeCase returns a new instance.
      const snaked = SomeSchema.snakeCase();
      // I'm simplifying, but obj is also an instance, because SomeSchema has, under properties, more instances of the same class.
      // At any rate, it's just relevant that `obj` is an instance of the class
      const obj = snaked.properties.nested?.value;
      console.log("OUTSIDE KEYS", Object.keys(obj.properties));
      obj.testFunc(obj);
      console.log("ABOUT TO RUN AGAIN");
      obj.testFunc(obj);

And here's the output

  console.log
    OUTSIDE KEYS [ 'snake_name', 'camel_name_nested' ]

      at Object.<anonymous> (common/utils/__tests__/object.test.ts:70:19)

  console.log
    KEYS [ 'snake_name', 'camelNameNested' ]

      at Object.testFunc (common/utils/object.ts:220:13)

  console.log
    KEYS2 [ 'snake_name', 'camel_name_nested' ]

      at Object.testFunc (common/utils/object.ts:223:13)

  console.log
    ABOUT TO RUN AGAIN

      at Object.<anonymous> (common/utils/__tests__/object.test.ts:72:19)

  console.log
    KEYS [ 'snake_name', 'camelNameNested' ]

      at Object.testFunc (common/utils/object.ts:220:13)

  console.log
    KEYS2 [ 'snake_name', 'camel_name_nested' ]

      at Object.testFunc (common/utils/object.ts:223:13)

The question: How the hell is this happening? How is obj as this different from obj as self? Or, in other words, why is this not referring to the same properties from within the testFunc function as from "without" when properties is called directly on obj`?

I'm happy to provide other code (let me know what), but I suspect it's a distraction, since the problem is so narrow.

What are the possible cases where the this binding gets broken like this? (It specifically seems to be the pre-snake-case value, but it seems to me that the functionality that "brought us here" is irrelevant, because the issue is obj.properties is just two different things in two different contexts

Sasha
  • 6,224
  • 10
  • 55
  • 102
  • Arrow functions do not have their own `this`, they simply use the one in from the lexical declaration. – VLAZ Aug 20 '23 at 17:26
  • You never pass any arguments to the `testFunc` - `self` should be `undefined` thus, you should be getting a TypeError when accessing `self.properties`. You do not have a [mcve] presented here. – VLAZ Aug 20 '23 at 17:29
  • Sorry, updated. I pasted the wrong code. I did indeed pass `obj`, which was the code that ran for the logs. Do you know where I can read more about the "lexical declaration" that `this` is coming from? (Or how I can get its "own `this`" in that function?) – Sasha Aug 20 '23 at 17:34
  • 1
    [What does "this" refer to in arrow functions in ES6?](https://stackoverflow.com/q/28371982) | [Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?](https://stackoverflow.com/q/34361379) | [How does the "this" keyword work, and when should it be used?](https://stackoverflow.com/q/3127429) – VLAZ Aug 20 '23 at 17:35
  • Thank you! Switching from `testFunc = () => {}` to `testFunc() {}` fixed it! – Sasha Aug 21 '23 at 14:46

0 Answers0