1

I'm not getting what's happening in the below code. Why constructor function is enclosed inside another function and why both constructor and the function in which it is enclosed have given the same name? Also why enclosing function has made to be self invoked?

var Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
}());
var greeter;
greeter = new Greeter("world");
console.log(greeter.greet());
Loufs
  • 1,596
  • 1
  • 14
  • 22
user3760959
  • 457
  • 1
  • 6
  • 18
  • 1
    [IIFE](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) (function(){return 22;}`()`) – HMR Jan 12 '18 at 17:20
  • It's a form of using a function as a "class", with an immediately invoked function expression wrapped around it – Mark C. Jan 12 '18 at 17:21
  • Okay. But why it needed to be self invoked. And why constructor function and the enclosing function have same name? Could you give me a brief over it? – user3760959 Jan 12 '18 at 18:09

2 Answers2

2

You can consider the self-invocation function as kind of higher order function, that returns some another function with some configuration.

Okay, what that self-invocation function is doing? It does contain one constructor functions which hold one public property with name "greeting". Input parameter received from constructor function, get assigned to the greeting. After this signature, it's adding some helper function to this constructor function, with the help of prototype, which prints greeting message.

what does it mean by prototype? it's the one of the major pillar of javascript https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

Well! do we really need a self-invocation function for this? the answer is, nope! we can have this written in a simple way too, just like below,

function Greeter(message) {
    this.greeting = message;
}
Greeter.prototype.greet = function () {
    return "Hello, " + this.greeting;
}; 

var greeter;
greeter = new Greeter("world");
console.log(greeter.greet());

That's it! And it will give the exact result as above.

Then why that guy used the self-invocation function for it? I believe, cool design pattern always shines. That guy has a plan to write some factory function kind of thing which would give me a fully configured constructor function. In this case, the self-invocation expression is nothing but the so called factory.

Note: in the original post by you, the outer most Greeter is not a real function, that is a simple variable which holds some function, returned by that self invocation block. You can use any name for that variable.

Ravindra Thorat
  • 1,822
  • 1
  • 17
  • 24
  • Thanks. From where I read that code, it was mentioned as a form of using functions as class in Javsacript. I'm not getting how it's acting as class here. Could you explain? – user3760959 Jan 12 '18 at 18:41
  • I wouldn't call the IIFE a ["high-order function"](https://en.wikipedia.org/wiki/Higher-order_function). I'd also avoid calling it a "generator", since that term has [another meaning](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function%2A) in JS. Great explanation otherwise! – Nickolay Jan 12 '18 at 18:42
  • @user3760959 , function plays many roles in javascript. that's why functions are called as first class citizen in javascript. when you use a "new" keyword before the function invocation, that corresponding function acts as a class and returns a new instance, nothing else. NOTE: "class" never exist in javascript, not even in es6. its always been a function. – Ravindra Thorat Jan 12 '18 at 18:53
  • thank you so much, @Nickolay! totally agreed! that's why I used "kind of" words there. And I did use "generator" in a very rough way. perhaps "factory" would make more sense there – Ravindra Thorat Jan 12 '18 at 18:53
2

In this particular case there's no point in wrapping Greeter in an immediately invoked function (IIFE); Ravindra Thorat is right that rewriting results in (mostly) equivalent behavior.

This construct starts to make sense when you put more stuff inside the anonymous-immediately-executed-function, like the strict mode marker or a private variable (GREETING in example below):

var Greeter = (function () {
    "use strict";
    const GREETING = "Hello, ";

    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return GREETING + this.greeting;
    };
    return Greeter;
}());
var greeter;
greeter = new Greeter("world");
console.log(greeter.greet());
// console.log(GREETING) // not defined here -- only available inside the anonymous function

Updated to answer a comment:

Note that the value of the outermost variable Greeter is not the outer anonymous (nameless) function itself, but the result of its invocation. Compare:

var Greeter = (function() {...})() // the returned value is assigned to Greeter
var Greeter = (function() {...})   // the anonymous function without parameters is assigned to Greeter

Since the outer anonymous function ends with return Greeter, the value of the outermost Greeter variable is the function Greeter(message) declared inside the IIFE.

Basically everything inside the IIFE is unavailable outside it, except the explicitly returned object (the Greeter(message) constructor in this example).

Nickolay
  • 31,095
  • 13
  • 107
  • 185
  • Thanks. From where I read that code, it was mentioned as a form of using functions as class in Javsacript. I'm not getting how it's acting as class here. Could you explain that ? – – user3760959 Jan 12 '18 at 18:49
  • @user3760959: Where did you read that? Putting it this way is a bit confusing. What the IIFE does is it provides `Greeter` with its own private scope (if you insist on drawing parallels with classes you could say it provides you with functionality equivalent to private static variables or private helper classes) – Nickolay Jan 12 '18 at 19:01
  • Thanks for explaining. I am still confused over one thing. The function which is defined in the outermost variable 'Greeter' has no parameters in its definition. Still in the code, value 'world' was passed to it. How that function is getting this value ? And if the value is hold by the inner 'Greeter' function not by the outer one, then how is it possible so, as per its scope inner one is 'undefined' for outer side ? – user3760959 Jan 12 '18 at 19:24
  • Yes. I got it now. Thanks a lot. – user3760959 Jan 15 '18 at 06:45