"some expression" runs during the construction of the object so this refers to the object under construction as it is typical for constructor functions.
classWhatever{someMethod=(()=>{// IIFE body})();}
in this case the expression is an Immediately Invoked Function Expression (IIFE) - i.e. after the function expression creates the function, the function is immediately executed. All of this still happens inside the constructor function and the return value of that IIFE is assigned to the someMethod property of the object under construction.
Inside the IIFE this is copied to outerThis and the IIFE is the closure that creates the function that is assigned to someMethod. But given that all of this is still happening inside the constructor function this is still simply the object under construction.
This may make it more clear what is actually happening:
// Constructor FunctionfunctionWhatever(){// When invoked by `new`, i.e. `new Whatever()`// `new` passes the object under construction// as `this` to `Whatever`constmakeFunction=()=>{constouterThis=this;constbuiltFunction=()=>{return[outerThis,this];};returnbuiltFunction;};this.someMethod=makeFunction();// Note the lack of the a return statement/value// It's `new` that returns the constructed object// not `Whatever`.}constwhatever=newWhatever();const[outer,inner]=whatever.someMethod();console.assert(outer===inner);console.assert(outer===whatever);console.assert(inner===whatever);
functionjustSomeFunction(){constmakeFunction=()=>{constouterThis=this;constbuiltFunction=()=>{return[outerThis,this];};returnbuiltFunction;};this.someMethod=makeFunction();}// passing an object literal as `this` with `call`constobj={};justSomeFunction.call(obj);const[outer,inner]=obj.someMethod();console.assert(outer===inner);console.assert(outer===obj);console.assert(inner===obj);
This is why inside functions this is called the function context. It's the context that is passed to the function so it can do its job. If the function operates as a method the function context refers to the object to which it was invoked on. But in a constructor function the function context refers to the object under construction. So what this is depends entirely on how a function is invoked. Arrow function expressions change the rules - this refers to whatever this was in the creating closure when the arrow function was created. This means that arrow functions on super-types won't work for sub-types because sub-types are unable to pass in their own this into the arrow function.
classA{myArrow=()=>{console.log('A.myArrow()');}myMethod(){console.log('A.myMethod()');}}classBextendsA{myArrow=()=>{super.myArrow();// arrow function exists on // public class field of A but// but is not available on // the prototype chain via `super`console.log('B.myArrow()');}myMix(){super.myArrow();// same problemconsole.log('B.myMix()');}myMethod(){super.myMethod();// just worksconsole.log('B.myMethod()');}}letmyB=newB();myB.myMethod();// 'A.myMethod()'// 'B.myMethod()'myB.myMix();// Uncaught TypeError: (intermediate value).myArrow is not a function at B.myMixmyB.myArrow();// Uncaught TypeError: (intermediate value).myArrow is not a function at B.myArrow
Thanks for clarification, I had assumed that IIFE captured this as class is created in scope of globalThis, but now I understand that fields of class are invoked inside constructor.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
thanks for the insights and corrections
You made a mistake in the constructor:
There are no classes in JavaScript - just objects.
MDN: Classes
i.e. classes are just a convenience for creating objects in JavaScript - nothing more - objects are not tied to some kind of static class membership.
Your second example isn't surprising:
w1andw2are separate objects with different references. So your original comparison will fail just asw1 === w2will fail.Meanwhile the reference returned by
someMethodis identical to the reference of the object itself.thanks for the insights and corrections
Well I was wrong, I learned that
thisis even available as arrow function that is created inside the class.To understand
thisin arrow functions you need to understand closures/scope.Because
thisinside an arrow function refers to whateverthiswas in the closure at the point in time the arrow function was created.Dissecting ...
thisrefers to the object under construction as it is typical for constructor functions.someMethodproperty of the object under construction.thisis copied toouterThisand the IIFE is the closure that creates the function that is assigned tosomeMethod. But given that all of this is still happening inside the constructor functionthisis still simply the object under construction.This may make it more clear what is actually happening:
Similarly with Function.prototype.call():
This is why inside functions
thisis called the function context. It's the context that is passed to the function so it can do its job. If the function operates as a method the function context refers to the object to which it was invoked on. But in a constructor function the function context refers to the object under construction. So whatthisis depends entirely on how a function is invoked. Arrow function expressions change the rules -thisrefers to whateverthiswas in the creating closure when the arrow function was created. This means that arrow functions on super-types won't work for sub-types because sub-types are unable to pass in their ownthisinto the arrow function.For an interesting application of closures see OOP with Functions in JavaScript.
Thanks for clarification, I had assumed that IIFE captured
thisasclassis created in scope ofglobalThis, but now I understand that fields of class are invoked inside constructor.