Javascript return with colon
Asked Answered
F

3

55

I am learning JavaScript and have come across of the structure below:

var Test = (function () {

  function func1() {
      //do something.....
  }

  function func2() {
      //do something.....
  }

  function func3() {
      //do something.....
  }

  return {
      func1: func1,
      func2: func2,
      func3: func3
  };

})();

I am wondering what the return block is doing. Is this a very commonly used JavaScript structure? Please let me know where can I get more information about this.

Frizette answered 10/9, 2015 at 7:48 Comment(0)
G
71

This is the Revealing Module Pattern.

The returned object contains references to the functions defined inside the IIFE. So the functions defined inside are private to the anonymous function.

But if you want to use the inner functions outside, you can use the returned object.

The value of Test will be

var Test = {
    func1: func1,
    func2: func2,
    func3: func3
};

And you can call func1 from outside as

Test.func1();

This is the way Javascript emulate class. As there is no visibility specifiers using Module pattern, variables/methods can be make public/private.

enter image description here

The revealing module pattern is inspired from Module pattern. In revealing module pattern, only reference to the private variables/methods is returned in an object.

The main idea behind the pattern is avoiding evil global variables. This looks similar to IIFE except an object is returned instead of function. The variables/methods defined inside the IIFE are private to the function. To access any variable/method inside the IIFE, it needs to be added in the returned object and then it can be accessed from outside of IIFE. This pattern takes advantage of closures, so the variables/methods defined inside the IIFE are accessible even after the object is returned.

From Addy Osmani's book Learning Javascript Design patterns

The Revealing Module pattern came about as Heilmann was frustrated with the fact that he had to repeat the name of the main object when we wanted to call one public method from another or access public variables. He also disliked the Module pattern’s requirement for having to switch to object literal notation for the things he wished to make public.

The result of his efforts was an updated pattern where we would simply define all of our functions and variables in the private scope and return an anonymous object with pointers to the private functionality we wished to reveal as public.

Advantages:

  1. Encapsulation. The code inside the IIFE is encapsulated from outside world
  2. Clean, organized and reusable code
  3. Privacy. It allows to create private variables/methods. The private variables/methods cannot be touched from outside of the IIFE.

Disadvantages:

  1. If a private function refers to a public function, that public function can't be overridden

Further Reading:

  1. https://en.wikipedia.org/wiki/Module_pattern
  2. https://carldanley.com/js-revealing-module-pattern/
  3. How to use Revealing module pattern in JavaScript

EDIT

From comment from @Mike

It's of note that it's common to create an object (eg, var me = {};) and then declare the would-be public members on it (me.func1 = function() { /* ... */ };), returning that object at the end (return me;). This avoids the repetition that we see in the return statement of OP's code (where all the public stuff is repeated).

Gabo answered 10/9, 2015 at 7:50 Comment(1)
It's of note that it's common to create an object (eg, var me = {};) and then declare the would-be public members on it (me.func1 = function() { /* ... */ };), returning that object at the end (return me;). This avoids the repetition that we see in the return statement of OP's code (where all the public stuff is repeated).Cutin
N
15

It's a literal object in the return statement. It's like creating an object and then returning it:

var obj = {
    func1: func1,
    func2: func2,
    func3: func3
};
return obj;

The literal object syntax creates an object and sets its properties, just like:

var obj = new Object();
obj.func1 = func1;
obj.func2 = func2;
obj.func3 = func3;
return obj;

The purpose of returning the object is to reveal the functions inside the function to the code outside, while creating a scope for private variables that the functions can use.

When not using private variables, the code does the same thing as:

var Test = {
  func1: function() {
      //do something.....
  },
  func2: function() {
      //do something.....
  },
  func3: function() {
      //do something.....
  }
};

Private variables are declared inside the function scope, and are only reachable by the functions inside it. Example:

var Test = (function () {

  var name;

  function setName(str) {
    name = str;
  }

  function getName() {
    return name;
  }

  return {
      setName: setName,
      getName: getName
  };

})();

Test.setName("John Doe");
var name = Test.getName();
Nostradamus answered 10/9, 2015 at 7:55 Comment(4)
Why would you use new Object() or string notation when not necessary?Equiangular
@Seiyria: To do the same as literal object notation without literal object notation. I just changed the string notation to regular property identifiers though. :)Nostradamus
I guess my point was that var object = {} is a lot better than var object = new Object(). It makes more sense and performs better.Equiangular
@Seiyria: Yes, it does, but that is an object literal, and I wanted to show what the object literal does.Nostradamus
N
1

That works like a class in other programming languages. Therefore, you can access the public func1 member using Test.func1 and call it like a normal function using Test.func1().

Needy answered 10/9, 2015 at 7:51 Comment(1)
Thanks for the feedback, downvoters. Gotta' love the 2016 SE community.Needy

© 2022 - 2024 — McMap. All rights reserved.