Reputation: 6282
After discovering TypeScript I've played around with the online compiler and the resulting JavaScript code made me wonder about function expressions.
A simple TypeScript class:
class Person {
firstName: String = "John";
lastName: String = "Doe";
}
Results in the following JavaScript code:
var Person = (function () {
function Person() {
this.firstName = "John";
this.lastName = "Doe";
}
return Person;
})();
That made me wonder why they chose to go with self-executing function, when something simpler might have sufficed. What is the purpose of an inner function with a name identical to the variable?
And why didn't they go with something simpler, such as:
var Person = function() {
this.firstName = "John";
this.lastName = "Doe";
};
Or even:
function Person() {
this.firstName = "John";
this.lastName = "Doe";
}
As far as I can tell using function expressions on a global scope offers no advantages, only the disadvantage of not being able to call the function before it was declared.
Upvotes: 0
Views: 129
Reputation: 276259
It helps with inheritance. It allows them to capture the base class with a rename to _super
which helps with code generation e.g.:
class Foo{
}
class Bar extends Foo{
}
becomes :
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var Foo = (function () {
function Foo() {
}
return Foo;
})();
var Bar = (function (_super) {
__extends(Bar, _super);
function Bar() {
_super.apply(this, arguments);
}
return Bar;
})(Foo); // Notice base class is captured here
This is good practice in JS as well. For example, if you kept using Foo
in this example instead of _super
and you were to change the base class you would have a whole avenue of headaches which can be avoided.
Upvotes: 2
Reputation: 220944
You really don't want to be able to invoke a class before its declaration has executed. Consider this code:
class Person {
static nameSeparator = ' ';
public fullName: string;
constructor(public firstName, public lastName) {
this.fullName = firstName + Person.nameSeparator + lastName;
}
}
And its generated form:
var Person = (function () {
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = firstName + Person.nameSeparator + lastName;
}
Person.nameSeparator = ' '; // <-- Important!
return Person;
})();
Do you want code that accidently runs before the indicated line to run with undefined behavior (in this case, Person.fullName is "JohnundefinedSmith"), or just fail?
In other cases, the class simply won't work at all:
class Person {
constructor(public firstName, public lastName) {
// Will fail until Person.prototype.getFullName gets set
console.log('New person, name = ' + this.getFullName());
}
getFullName() {
return this.firstName + " " + this.lastName;
}
}
Upvotes: 1
Reputation: 3933
This allows for you to make some private variables.
In JS:
var Person = (function () {
var firstName, lastName; //static private vars
function Person(fName, lName) {
firstName = fName;
lastName = lName;
}
return Person;
})();
Upvotes: -1