2

I am new to Javascript and am still getting my head round the various ways of creating objects i.e constructor+new, prototypal, functional & parts.

I have created what I think is an object factory using the module pattern and want to know what the correct method of calling an internal method would be. Is it via this or function name.

Here is my module:

function chart() {
    function my() {
        // generate chart here, using `width` and `height`
    }

    my.sayHi = function(){
        console.log('hi');
        my.sayBye();
    };

    my.sayBye = function(){
        console.log('Bye');
    };

    return my;
    }

var test = chart();
test.sayHi();

You can see that the first function calls the second using my.sayBye() or is it better to use this.sayBye(). Both produce the same result and run without error.

timebandit
  • 794
  • 2
  • 11
  • 26
  • Depends. Using `this` can become... interesting if, say, you "borrow" `my.sayHi` and call it from another execution context. – Dave Newton Jun 20 '15 at 11:58
  • As, you say, both do work. Use whatever you like better, [if you don't expect a specific behaviour in special cases](http://stackoverflow.com/questions/10711064/javascript-object-literal-reference-in-own-keys-function-instead-of-this) – Bergi Jun 20 '15 at 12:27

2 Answers2

5

The module pattern allows you to dispense with the 'this' variable if you want to. I would probably rewrite the above code to look like this and then the question becomes moot.

function chart() {
    var hiCount = 0;

    function sayHi(){
        console.log('hi');
        hiCount++;
        sayBye();
    };

    function sayBye(){
        console.log('Bye');
    };

    return {
       sayHi : sayHi,
       sayBye: sayBye
    };
}

var test = chart();
test.sayHi();

In the above code all is defined within the function chart. As JavaScript's scope is at the function level every time the chart function is called a new set of functions will be defined. And a new set of variables can also be defined that are private to the function as they are defined in the function and are not accessible from outside. I added hiCount as an example of how you could do this. The Module pattern allows privacy in JavaScript. It eats more memory than the prototype pattern though as each time a function is declared it is not shared between other instances of the same class. That is the price you have to pay in Javascript to have class variables that are private. I willingly pay it. Removing 'this' from my code makes it easier to understand and less likely that I will fall into problems of misplaced scope.

Aran Mulholland
  • 23,555
  • 29
  • 141
  • 228
  • In a way your doing the same thing as I am. In that, I am declaring an empty object, declaring methods against it using dot notation and then returning the object. You are, declaring some functions first, then adding these as methods into your return object. So they are the same sort of thing. However, I do think your way is clearer and less open to confusion if coming back to the code after a few months by, as you say, dispensing with **this** – timebandit Jun 20 '15 at 12:29
  • I like my way better because it represents a class. I have the private functions and variables then I choose which functions to expose. Using this pattern you can have private variables and internal class functions that never get exposed. And you never have to think about the scope, it is always just what is captured by the closure in the enclosing functions definition. Your code wasn't far off what I had. – Aran Mulholland Jun 20 '15 at 12:32
  • An advantage I can see with my original code is that allows for method chaining if all the functions return the **my** function object. I cant see how you could do this with your alternative. – timebandit Jun 20 '15 at 12:51
  • Yeah fair enough, I suppose it depends on your purpose. You can do the same thing by defining the my variable at the top using the pattern I have outlined. You just return it from any function called (unless those functions need to return something else). I guess my illustration is designed to show you that using the closure at the function level you can dispense with using the this variable. – Aran Mulholland Jun 21 '15 at 13:02
  • Yes very true. I'm learning Crockfords book, and in that vain I would like to get in the habit of creating durable objects, ones that do not make use of **this** and are hence secure. – timebandit Jun 21 '15 at 13:05
  • Crockford taught me a lot but he led me down some paths I wish I hadn't have. Don't trust everything he says, in some things he is (in my opinion) very wrong. I would not recommend using his JSLint tool either. It conforms your code to his opinion which is not always right. I kind of wish I had never read one of his books, when I look at some of my old code that followed his patterns I am aghast. – Aran Mulholland Jun 21 '15 at 13:13
  • Hmm yes food for thought. Can you recommend something for me to read and learn form? – timebandit Jun 21 '15 at 13:15
  • Depends where you are in your journey I suppose, I liked http://shop.oreilly.com/product/9780596806767.do and http://www.manning.com/resig/ – Aran Mulholland Jun 21 '15 at 13:21
  • Oh and I enjoyed this, there is a video presentation of it around somewhere: http://www.slideshare.net/nzakas/scalable-javascript-application-architecture – Aran Mulholland Jun 21 '15 at 13:23
  • Then again, can you trust my opinion? I'm just some guy on stack overflow :) – Aran Mulholland Jun 21 '15 at 13:23
  • Well we all need to try it and see sometimes. Thanks!! – timebandit Jun 21 '15 at 13:27
1

Using "this" is better approach because you would be able to bind the function directly to the parent function object.And you dont need to return anything from the function. where as in your case you are explicitly returning another function Here is the use of "this" approach

function chart() {
 this.sayHi = function(){
    console.log('hi'); 
 }
}

var test = new chart();
test.sayHi();

Using this approach you would be able to call anything in the prototype of function "chart" Eg

chart.prototype.hello = function(){
 console.log('hello')
}

So you would be able to call the hello function from the same object(test)

Mohit
  • 569
  • 2
  • 8