0

I have been using the latest version of Vue.js and I really like the composition API but as I can't use vue for all my projects I have been experimenting with getting a similar syntax with native JS.

I have found that I can emulate es6 classes with the following code with the advantage of a syntax closer to Vue, no need to prefix all my variables with this.

function Component (node) {

   const test1 = "I am a private variable"
   this.test2 = "I am a public variable"
      
   getProps = () => {
      return test1; // I am a private method with access to component variables
   }

   onTimeout = (callback) => {
      setTimeout(callback, 1000);
   }
   
};

function Media (node) {
      
   Component.call(this, node); // copies public variables and methods 
   const sup = Object.assign({}, this); // acts like super in es6 classes
   const props = getProps();

   console.log(sup)
   console.log(props)

   onTimeout(() => {
      console.log("I am executed on timeout")
   })
      
}

new Media();

While it all seems to be functional and the browser doesn't throw any errors, typescript does not like the getProps or extend methods and throws the error Cannot find name 'getProps', when trying this code on codesandbox.io it also throws an error getProps is not defined.

If you run this code snippet here on stackoverflow it should also work.

While I could prepend this. to the methods that would make them public and no long private.

So my questions are:

  • is this valid code?
  • what exactly is going on here, if it is not valid why does this work in the browser?
  • would there be any problem in using this in a production environnement?
  • if so is there any other way I could accomplish the same thing?
  • if not how do I tell typescript to not generate an error for the 2 methods?
The Sloth
  • 367
  • 5
  • 18
  • Why are you limited to ES5? I believe all the modern browsers are supporting most ES6 syntax at this point... – Alexander Nied Sep 27 '22 at 13:27
  • 3
    `getProps` is an implicit global and a terrible practice. For example, you cannot have two different modules, then since all will share the same `getProps`. – VLAZ Sep 27 '22 at 13:28
  • 2
    To get warned of issues like implicit globals, always use [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) (where they're the error they always should have been). – T.J. Crowder Sep 27 '22 at 13:31
  • This is far too broad and open-ended a question for SO's Q&A format (especially #4), please see the [help]. – T.J. Crowder Sep 27 '22 at 13:39
  • @AlexanderNied Sorry I probably wasn't very clear I am not limited to ES6 I am just not a fan of the ES6 class syntax. – The Sloth Sep 27 '22 at 13:40
  • 1
    *"is this valid code?"* **Yes**, in that it's syntactically correct (in loose mode) and runs. **No**, in that it doesn't do what you think it does. *"what exactly is going on here, if it is not valid why does this work in the browser?"* That code makes use of closures for private data (that part's fine), but then creates **global** variables called `getProps` and `onTimeout`, overwriting them with updated versions every time `Component` is called. That's almost certainly not what you meant to do. It's also why `Media` can call `getProps`; it's a global, **any** code can call it. ... – T.J. Crowder Sep 27 '22 at 13:41
  • 1
    ... More on my old anemic blog: [*The Horror of Implicit Globals*](http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html) *"would there be any problem in using this in a production environnement?"* Yes, subsequent calls to `Component` overwrite the globals created by previous calls. – T.J. Crowder Sep 27 '22 at 13:41
  • 1
    @TheSloth - If you don't like `class`, you can use `function` for most of it. [My answer here comparing the two](https://stackoverflow.com/a/30783368/157247) should help with the syntax. If you want to do pseudo-private stuff and concise syntax even for hierarchies of classes, I did [a library back in the day](http://blog.niftysnippets.org/2012/04/announcing-lineage.html). I'm not recommending it (I'd just either use `class` or not use `new` at all), but it seems in the wheelhouse of what you're trying to do. :-) – T.J. Crowder Sep 27 '22 at 13:45
  • @T.J.Crowder Thank you it seems so obvious now you say it. I assumed as JS wasn't giving me an error that it was somehow bound to the function. – The Sloth Sep 27 '22 at 14:34
  • @VLAZ I had no idea implicit globals even existed, it all makes sense now thanks – The Sloth Sep 27 '22 at 14:38
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/248383/discussion-between-the-sloth-and-t-j-crowder). – The Sloth Sep 27 '22 at 15:00

0 Answers0