Is there any way to have Object prototype methods nested within an object's definition so that it keeps best readability? The main concern is the memory footprint involved, and efficiency.
It's frustrating to come from a language like C# or even see that PHP has better object implementation (In My Opinion). Are there any libraries or something that allows for Class-like OOP that I'm used to for Javascript?
I guess I'm looking for the encapsulated feel from the nesting, rather than being outside of the enclosure. I'm also used to languages where you make a Class and it's the blueprint for the objects that you construct. Maybe I've been mistaken all this time and those other languages have been duplicating the code within the memory, but I would imagine that they are optimised to have the internal methods point at a single memory reference. Is javascript meant to be like this, Why, Is it lagging behind, am I doing it wrong, are there other ways?
I know in compiled languages you would have classes where each had its own file - at that point I could feel semi justified without the nesting. This doesn't work for the web paradigm - that everything should be in as few of requests as possible. Is there something out there that I should look into that would compile JS into a single file?
For example
"The Wrong Way": The method/function: getFullName is enclosed in Person.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.getFullName = function() {
return this.firstName + " " + this.lastName;
};
}
"The Right Way" Using prototyping
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.getFullName = function() {
Here's what I've come up with after seeing the transpilers for TypeScript and Babel for ES6.
Here's the original question's code in TypeScript & ES6 & their transpilations (is that a real word?)
TypeScript:
class Person {
firstName: string;
lastName: string;
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return this.firstName+' '+this.lastName;
}
}
Transpiled (Most simplistic out the results): I guess this would be the straight forward simple answer to my original question.
var Person = (function () {
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.getFullName = function () {
return this.firstName + ' ' + this.lastName;
};
return Person;
})();
ES6:
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return this.firstName+' '+this.lastName;
}
}
Transpiled:
"use strict";
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Person = (function () {
function Person(firstName, lastName) {
_classCallCheck(this, Person);
this.firstName = firstName;
this.lastName = lastName;
}
_createClass(Person, [{
key: "getFullName",
value: function getFullName() {
return this.firstName + " " + this.lastName;
}
}]);
return Person;
})();
Transpiled Loose Mode:
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Person = (function () {
function Person(firstName, lastName) {
_classCallCheck(this, Person);
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.getFullName = function getFullName() {
return this.firstName + " " + this.lastName;
};
return Person;
})();
To my understanding TypeScript is a "superset" that builds on top of JS, and one of the obvious additions is explicit Types. ES6 and higher is what we know of as JavaScript, they just have not yet been fully adopted and integrated into most modern browsers completely yet. Which is why transpilers exist to compile the code from ES6 to ES5 which seems to be currently fully supported by modern browsers.
In conclusion...
As much as I love typed languages I think it might be overkill in JS, ES6 looks much more like the JS I'm used to seeing (even though that seems slightly contradicting to my original question comparing to C#/Java/PHP), then again ES6 is actually vanilla JS from the future ;) TypeScript seems to transpile down into simplistic JS, while ES6 adds a small overhead with some sanity functions. It's quite possible that TS handles some checks in the transpiling process - I'm sure a proper IDE would check for errors too before transpiling, while Babel's transpiled code would allow you to continue safely writing code after transpiling. The overhead from Babel doesn't seem to be much in terms of source code size compared to an actual project size. It is also hard to properly judge them from this small test case, along with the many options out there for transpilers.
Babel's ES6->ES5 loose mode without the sanity checks would be identical to TypeScript's code. The above code for the TS Transpiled would be the minimum vanilla javascript that is supported in modern browsers.
I'm a filthy IDE lover, it's nice to see TypeScript's online IDE with completion and Run, while Babel's is just a highlighter with a bit of basic help such as auto double quotes right now. I use Jetbrains' products, it's nice to see they have support for both TS and ES6.