skip to Main Content

I write JS (well, EcmaScript), but only relatively rarely.

When writing on a member function for an object, I naturally often use other member variables and functions multiple times; but I tend to avoid defining my own globals, and no less importantly, I make an effort to avoid aliasing globals with members I define.

Given that state of affairs, I’m annoyed by having to use this all the time, e.g.:

this.memberA = this.methodB(someInputParam, this.memberC);

I would really like to just say:

memberA = methodB(someInputParam, memberC);

and have memberA, methodB and memberC be looked up first in the scope of this, then in the global scope.

Can that be done?

2

Answers


  1. Using this has own benefits in terms of scoping, you can declare any parameters and local variables and they won’t clash with this‘ props. Otherwise you could use so called "hard objects", I was using them for years with success.

    Answerting the OP’s questions:

    1. Can you elaborate on the difference between the members in the "assign" statement and the other members?
      All public members should be assigned to this to be available on the instance.

    2. Can I do something similar without defining a constructor?
      No. The pattern is about using only a constructor to build your instance. All variables inside it are private, the public ones are assigned to this. Otherwise there’s with statement which isn’t recommended.

    3. You can use a mixin pattern to gradually enhance your instances with other instances.

    function MyClass(){
      
      Object.assign(this, {publicMethod, publicProp: 'public'});
      
      let memberC = 2, memberA = null;
      
      function methodB(someInputParam, param2){
        return someInputParam + param2;
      }
      
      function publicMethod(){
        memberA = methodB(2, memberC);
        console.log(memberA);
      }
      
    }
    
    const my = new MyClass;
    my.publicMethod();
    Login or Signup to reply.
  2. There is no sensible, idiomatic, and ergonomical way to do this. Nor is it likely to happen in the future. Any solution would be a huge trade-off in terms of readability, maintainability, and hackyness.

    The reason is that when trying to reference an identifier, JavaScript would always use the scope resolution, while referencing an object’s property is different to that. Any change to such mechanics would need to go against fundamental design of JS, thus lead to sacrificing features and code clarity for very little (if any) benefit.

    It is also unlikely this would ever be revised in JavaScript, as it would still require to deal with legacy code.

    The best bet here is to write a plugin for an existing transpiler that changes to check this first then the identifier. So, from

    foo(bar)
    

    to

    (this["foo"] ?? foo)(this["bar"] ?? bar)
    

    However, I would advise against doing even that. The benefit is too small and the risk too great.

    Consider using a proper linter which would tell you if you use an undefined variable (in cases where you missed the this) and configure your editor to show identifiers and properties differently, to make it easy to distinguish at a glance which one of the two you have. If you use any type checking option (like TypeScript or Flow or others), there would also be an error when bar and this.bar (assuming both exist) are of different types but used in the wrong place.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search