Jonathan002
Jonathan002

Reputation: 10278

Are Typescript class objects slower in performance by wrapping together their methods?

I could be mistaken but by looking at typescripts playground I noticed that they wrap their classe's methods together with the object variable which feels like it may reduce performance every time I call a new object.

e.g. Typescript Playground Output of Class

var FatObject = (function () {
   function FatObject(thing) {
       this.objectProperty = 'string';
       this.anotherProp = thing;
   }
   FatObject.prototype.someMassivMethod = function () {
       //many lines of code 
       //...
       //...
       //...
       //.......................
    };
   return FatObject;
}());

var thing = 'example';
var objOne = new FatObject(thing);
var objTwo = new FatObject(thing);
var objThree = new FatObject(thing);
var objFour = new FatObject(thing);

I feel that if I write massive methods, each time I create a new object from the class I will also be compiling these massive methods.

Rather than declaring the methods outside the function name when I create new objects.

e.g. old way:

function ThinObj(thing) {
    this.anotherProp = thing;
    this.objectProperty = 'string';
}

ThinObj.prototype.someMassivMethod = function() {
    //many lines of code 
    //...
    //...
    //...
    //..................
}

const thing = 'example'
let objOne = new ThinObj(thing);
let objTwo = new ThinObj(thing);
let objThree = new ThinObj(thing);
let objFour = new ThinObj(thing);

Can anyone clarify if:

A: I am loading 4 types of functions in memory in the typescript example (or overwriting them since prototype is used - I'm still shakey with my understanding of prototype).

B: If more compiler work is happening with Typescript wrapping the methods together?

Thanks

Upvotes: 6

Views: 2627

Answers (1)

Aluan Haddad
Aluan Haddad

Reputation: 31803

The closure is only executed when the class itself is created. This is known as an immediately invoked function expression (IIFE) and can be recognized by the characteristic ()) or )() after the function's closing }.

This means it is only executed once and thus that you have nothing to fear from it regarding performance (in general functions are cheaper than people think anyway).

Furthermore, this pattern of class generation is common and idiomatic as it encapsulates the definition of a class in a single expression.

Importantly, it is also necessary to correctly transpile classes which are not a TypeScript feature but an ECMAScript feature. As per the ES2015 specification (the standard that added the class feature), class definitions are not hoisted, but function definitions always have been, so the correct translation is indeed assignment of an IIFE result to a var.

To illustrate this in code:

console.log(ThinObj);
// Does not cause an error and thus violates the specification for ES2015 classes
var t = new ThinObj('thing'); // Succeeds because function is hoisted

function ThinObj(thing) {
  this.thing = thing;
}

vs

console.log(ThinObj);
// Causes an error and therefore complies with the specification for ES2015 classes
var t = new ThinObj('thing'); // Fails because var is `undefined` before initialization

var ThinObj = (function ThinObj() {
  function ThinObj(thing) {
    this.thing = thing;
  }
  return ThinObj;
}());

Upvotes: 5

Related Questions