1

Primarily I'm a C# developer learning Javascript of late. I was trying out ES6 classes. I expected ES6 classes to behave like regular classes, but finding many anomalies.

class Test{
    constructor(){
        console.log("Constructor Invoked");
    }

    instanceMethod1(){
        console.log("instanceMethod1 Invoked");
    }

    instanceMethod2InvokesInstanceMethod1(){
        console.log("instanceMethod2InvokesInstanceMethod1 Invoked");
        this.instanceMethod1();
        //instanceMethod1(); //wont work in JS, but will work in C#
    }

    instanceMethod3InvokesStaticMethod1(){
        console.log("instanceMethod3InvokesStaticMethod1 Invoked");
        Test.staticMethod1();         
        //staticMethod1(); //Wont work in JS, but will work in C#
    }

    static staticMethod1(){
        console.log("staticMethod1 Invoked");
    }

    static staticMethod2InvokingStaticMethod1(){
        console.log("staticMethod2InvokingStaticMethod1 Invoked");
        this.staticMethod1();
        Test.staticMethod1();
        //staticMethod1(); //Wont work in JS, but will work in C#
    }

    static staticMethod3InvokingInstanceMethod1(){
        console.log("staticMethod3InvokingInstanceMethod1 Invoked");
        new Test().instanceMethod1();  
        //this.instanceMethod1(); //wont work 
    }
}

var ob = new Test();
ob.instanceMethod1();
ob.instanceMethod2InvokesInstanceMethod1();
ob.instanceMethod3InvokesStaticMethod1();

Test.staticMethod1(); 
Test.staticMethod2InvokingStaticMethod1();
Test.staticMethod3InvokingInstanceMethod1();

My Questions:

  1. Inside instanceMethod2InvokesInstanceMethod1 - Why calling instanceMethod1() wont work? Instance methods can't be invoked without an instance and hence calling an instance method within an instance method should make sense right?
  2. Inside instanceMethod3InvokesStaticMethod1 - Test.staticMethod1() will work is fair enough. But why cant we directly call staticMethod1 ?
  3. Inside staticMethod2InvokingStaticMethod1 - How this.staticMethod1() works ? What is the this object here ?
  4. Inside a static method, this.staticMethod1() works, but not this.instanceMethod1(). Why ? I guess answer to question 3, should help answer this question.

Could someone please help me here.

Boney
  • 2,072
  • 3
  • 18
  • 23
  • Not sure why you expected `this.instanceMethod1();` to work in a static method. That doesn't even work in any other class system?! – Bergi May 10 '17 at 17:13
  • @Bergi. Yes it is true it wont work in any other class system. My question can be rephrased to: If `this.staticmethod1()` works inside a static method, why doesnt `this.instanceMethod1()` since `this.staticmethod1()` itself didnt make sense to me. – Boney May 11 '17 at 01:11

1 Answers1

2

Your first problem is assuming that Javascript behaves like C++. There are some similarities, but many differences. You should not immediately EXPECT that something that works in C++ will work in Javascript. They are not the same language and this is a common problem when C++ developers start learning Javascript (it happened to me too).

Inside instanceMethod2InvokesInstanceMethod1 - Why calling instanceMethod1() wont work? Instance methods can't be invoked without an instance and hence calling an instance method within an instance method should make sense right?

No, Javascript is not C++ and does not offer that feature. You must use an object prefix when calling a method, even inside a method of that object.

Inside instanceMethod3InvokesStaticMethod1 - Test.staticMethod1() will work is fair enough. But why cant we directly call staticMethod1 ?

Again, not a feature of Javascript.

Inside staticMethod2InvokingStaticMethod1 - How this.staticMethod1() works ? What is the this object here ?

You will need to learn the rules for how Javascript sets the value of this. It is generally set based on how the method is called (though there are some ways to supercede that (like with arrow functions). See Six ways this gets set for reference info.

In this specific question, because you called staticMethod2InvokingStaticMethod1 like this: Test.staticMethod2InvokingStaticMethod1();, the this pointer inside that function will be set to Test which means you can then call other static methods of Test by reference this.someOtherStaticMethod(). This is the most basic rule for how this is set. If you call obj.method(), then inside of method, the this pointer will be set to obj.

What is important to realize in Javascript is that a method is just an ordinary function that happens to be a property of some other object. It has no particularly binding to any instance. It only gets a binding to an instance when such a binding is specified in how the method is called. The one exception to this is arrow functions which are not used for methods. In those cases, a function can be declared with the arrow syntax and it's this value will be set to the lexical value of this at the point of declaration. If you're just starting to learn this, I'd suggest you skip arrow functions until you have everything else about this firmly in your grasp. They were not part of the language until a couple years ago so you can write perfectly fine Javascript without them (they are mostly a syntax shortcut for some purposes).

Inside a static method, this.staticMethod1() works, but not this.instanceMethod1(). Why ? I guess answer to question 3, should help answer this question.

Yes, as you expected, same answer as 3.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thank you for the detailed explanation. Regarding this statement: "this pointer inside that function will be set to Test". this could even be set to the class ? – Boney May 10 '17 at 16:25
  • @Boney: `this` is set to whatever is "before the dot". If you `bar.foo()` then `this` inside `foo` will refer to the value of `bar` (there are exceptions. The value of `bar` can be any object (or even be a promitive), including function objects (classes are nothing but functions). – Felix Kling May 10 '17 at 16:33