-1

Lately I've been learning JS module pattern and I've seen at least 3-4 ways to create function expressions with public and private properties. My problem is I don't understand what's the best difference between them and what's the best approach / best practice.

The syntax on the 4 examples below are different but all of are invoked the same way. Can you explain me what's the difference between them?

Example A - I declare function func() and return only the method/function name.

var funcA = function() {
    var hi = "hello";

    function bye() {
        return 'bye';
    }

    function hello() {
        return hi;
    }

    return {
        hello: hello
    }
}();

Example B - here I declare foo = function() and return only the method/function name.

var funcB = function() {
    var hi = "hello";

    var bye = function() {
        return 'bye';
    }

    var hello = function() {
        return hi;
    }

    return {
        hello: hello
    }
}();

Example C - here I declare foo = function() inside the return

var funcC = function() {
    var hi = "hello";

    var bye = function() {
        return 'bye';
    }

    return {
        hello: function() {
            return hi;
        }
    }
}();

Example D - same as prev but all the function is wrapped in ().

var funcD = (function() {
    var hi = "hello";

    var bye = function() {
        return 'bye';
    }

    return {
        hello: function() {
            return hi;
        }
    }
})();

In each case if I want to call hello() I just write funcX.hello() and all of them return "hello"

But all of them are created by different ways. What's the correct one? If there is a correct way.

Thanks.

sandrina-p
  • 3,794
  • 8
  • 32
  • 60
  • 1
    `bye` isn't declared, so it goes global. – Daniel A. White Nov 22 '16 at 14:49
  • There's no big difference between any of them, expect for the fact that you're not using `var` to declare `bye` and `hello` in some of these examples and they thereby become global variables. If you fixed that, they'd all be equivalent for all intents and purposes. – deceze Nov 22 '16 at 14:52
  • ups the var was a missing in the example. i fixed that. – sandrina-p Nov 22 '16 at 14:56
  • @deceze true. The only slight difference would be with hoisting - if you were to use `hello()` inside `bye()` (with the current code structure) it won't work if it's `var hello = function()` but will if it's declared as `function hello()`. But that's honestly minor - these would all be pretty much the same. – VLAZ Nov 22 '16 at 14:56
  • @vlaz Since none of these functions are being called, that indeed is a theoretical difference. The resulting `func*` "modules" will all be identical. (Except that the methods may not be named, but that's getting really obscure…) – deceze Nov 22 '16 at 14:58
  • I guess the one I'd personally prefer is 1. or 2. (not much difference) basically because then it's a bit easier to decorate the function afterwards - you can do `return hello: _.memoize(hello)` for example. – VLAZ Nov 22 '16 at 14:58
  • So there is no difference in performance is that right? It's only a option of choice.. – sandrina-p Nov 22 '16 at 14:58
  • 1
    It's worth noting that there are no "methods" in JavaScript, there are only functions as properties on objects. It hasn't a special status like in Java, it's another property whose value is a function. – Madara's Ghost Nov 22 '16 at 14:59
  • @SandrinaPereira yes, they should work and behave the same. Not real "best" to choose from. Code styles/personal preferences will have way more weight, than anything technical. – VLAZ Nov 22 '16 at 15:00
  • 1
    If you care about performance, ***benchmark it***. And no, there won't be any discernible difference you will ever notice. – deceze Nov 22 '16 at 15:00
  • @deceze what do you mean by _benchmark it_? – sandrina-p Nov 22 '16 at 15:01
  • Write code, run it, time it, see which is faster. E.g. http://jsperf.com – deceze Nov 22 '16 at 15:02
  • Okay, thanks guys for the explanation! – sandrina-p Nov 22 '16 at 15:03

1 Answers1

3

It's worth noting first, that leaving out the var keyword from bye and hello will actually make them global.

Now the difference between:

var hello = function () {}

return {
  hello: hello
};

And

return {
  hello: function () {}
};

Is none, because you're just passing the function either way. Storing the function in a variable has the advantage where you can use it in another place in scope.

Now one difference to be aware of is declaring the function.

var myFunc = function () {}

vs

function myFunc () {}

The ones with the keyword infront get brought into scope immediately, so they are available before you reach the declaration. With a var, that's not the case. For example

function a() {
  b();
}

a();

var b = function () {
  console.log('hi')
}

When a is invoked, it will throw an error because b is not defined. If you do it like this though:

function a() {
  b();
}

a();

function b() {
  console.log('hi')
}

It will work fine. This is known as hoisting. The first is called a function expression var thing = function() {} where the last is called a function declaration function thing() {}

agmcleod
  • 13,321
  • 13
  • 57
  • 96
  • Thanks for the explanation. My only concern here was best practices / performance and following what you said, there is no problems. I usually follow funcA() structure, so I think I'm making it right :) – sandrina-p Nov 22 '16 at 15:03
  • 1
    It comes down to preference to be honest. I've found it to differ on various projects i've been on, and from company to company. Once you start getting into more fancy stuff, have a look at maybe including https://github.com/feross/standard in your editor. It's not an official standard, but we've tried to adopt it at work to keep things consistent. – agmcleod Nov 22 '16 at 19:00