-1

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() {
CTS_AE
  • 12,987
  • 8
  • 62
  • 63
  • If you just want to wrap the right version in a block, use an IIFE. – Bergi May 13 '15 at 03:22
  • Or use ES6 `class` syntax and a transpiler. – Bergi May 13 '15 at 03:23
  • There are programs out there that will take a bunch of JS files and combine them into one larger JS file and when doing so also have options for "minimizing" to reduce the size of the resulting download file. – jfriend00 May 13 '15 at 03:32
  • 2
    It is unclear why defining the prototype methods right after the function definition is any less readable. It's a convention that is perfectly understandable. It's not like the prototype methods are buried in some other file. – jfriend00 May 13 '15 at 03:33
  • Also, Javascript is Javascript, not some other language. You should stop thinking that it should "feel" like other languages. Trying to make it work or behave or feel like other languages will just force you into doing weird things that are not optimal in Javascript. Learn the language as it is. Learn the common conventions used to program in it. Write code that IS Javascript, not code that "feels" like some other language you know. – jfriend00 May 13 '15 at 03:34
  • Thanks @Bergi for those acronyms, I didn't know them before and there's definitely some good articles out there about them. I really do like the ES6 class syntax I'm seeing but it looks like it's not very well supported yet even with transpilers. I'll have to keep researching on it. I hope we don't have to wait 1-2 years like html5/css3 for full support even though my stomach says yes... – CTS_AE May 13 '15 at 03:35
  • @jfriend00 It seems like with Javascript there's several ways to go about objects which doesn't seem very clear or straight forward. Everytime I want to write some nice OOP JS I feel like I have to relearn so much and each time I find out more such as this whole memory duplication if you nest the functions. Every article I read seems to have a different way of OOP for Javascript which leaves me feeling like I'm stuck in a tangled mess for which way to write code that I want to be manageable and not spaghetti code like all so much JS seems to be written. – CTS_AE May 13 '15 at 03:39
  • 1
    @CTS_AE: Have you ever written a javascript application that ran out of memory? No? Then just use what you like better. The performance difference is neglible for 99% applications that are written. – Bergi May 13 '15 at 03:43
  • Before ES6 (which offers a standardized syntax), there are several popular styles to choose from for defining reusable objects. Just pick one, learn it and use it as your convention. There's nothing spaghetti about it unless you don't really know the language and YOU write spaghetti code. That's not about an object definition convention, that's about how you define, organize and write clean code. – jfriend00 May 13 '15 at 03:44
  • @CTS_AE: Every ES6 transpiler does support basic `class` syntax. What they don't support are subclassable native constructors, but that's not what you need here. – Bergi May 13 '15 at 03:44
  • I'll definitely do more research on this route, and see if there are any pitfalls to it. Although it may be out of the scope of this question, support for programming patterns will definitely be taken into account. According to this article: http://javascriptplayground.com/blog/2014/07/introduction-to-es6-classes-tutorial/ and the link to the compatibility table ES6 looks scarily unsupported while ES5 looks very well supported. I'll have to learn the differences between the two or use something like mentioned that compiles ES6 into ES5. – CTS_AE May 13 '15 at 03:49
  • 1
    Using the prototype to store methods (what you call "The Right Way") is not universally agreed upon as the best way to do things. Watch this video if you want to understand that point of view: [Douglas Crockford - The Better Parts](https://www.youtube.com/watch?v=PSGEjv3Tqo0). I haven't yet decided to code this way myself, but there are some interesting points made and it's worth challenging the conventional thinking to understand these advantages. The summary of what he's recommending for object implementations starts at 23:00, but the earlier parts are useful too. – jfriend00 May 13 '15 at 04:02
  • @Bergi I definitely understand what you're getting at about memory consumption, I've seen people pinch KBs which may have been useful back in the day, but now days we have so many GBs of ram and high speed internet that it almost doesn't matter. It starts mattering when quantity is taken into account. I end up spending more time learning than doing it quick and possibly dirty, but I want to learn the different ways and standards to create proper manageable code. – CTS_AE May 13 '15 at 04:15
  • @jfriend00 I got a chance to watch that video, and there were some good points, it was definitely helpful. Which got back at the memory consumption topic too ;) – CTS_AE May 13 '15 at 19:50
  • 1
    see also the possible duplicate [Assigning methods *inside* the constructor function - why not?](http://stackoverflow.com/a/28256166/1048572) – Bergi Aug 05 '15 at 06:27

2 Answers2

1

Sounds like you're looking for TypeScript which answers pretty much all of your questions.

TypeScript is a free and open source programming language developed and maintained by Microsoft. It is a strict superset of JavaScript, and adds optional static typing and class-based object-oriented programming to the language.

http://www.typescriptlang.org/

Javascript is javascript, C# is C#, you can't compare the two directly. Javascript can be awesome and I would really recommend you reading up some more before jumping straight into TypeScript.

Here's a good starting point if you're interested: http://shop.oreilly.com/product/9780596517748.do

Jako Basson
  • 1,461
  • 12
  • 19
  • Very interesting, I like it, some of it seems odd, but it's nice to know that it compiles down to vanilla JS. It's interesting for me to see how the class gets compiled: http://www.typescriptlang.org/Playground how it does have the prototype contained. I just wish I better understood why the compiled code encloses the function in a function. It seems this transpiler does the about the same thing along with some extra sugar: https://babeljs.io/repl/ – CTS_AE May 14 '15 at 18:13
0

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.

CTS_AE
  • 12,987
  • 8
  • 62
  • 63
  • An interesting look through of TypeScript vs Coffee Script vs ES6 http://www.slideshare.net/NeilGreen1/type-script-vs-coffeescript-vs-es6 – CTS_AE Jun 14 '15 at 00:07