How to use Chain Pattern with Self Revealing Module Pattern in JavaScript?
Asked Answered
R

4

9

I have the below code:

filtersManager = (function ($) {

    var that = this;

    function configure() {

        // some work

        return that;
    };

    function process() {

       // some work

        return that;
    }    

    return {
        // public functions
        configure: configure,
        process: process
    };
}(jQuery));

but when it's called using the below it fails:

filtersManager.configure().process();

Error: Object doesn't support property or method 'process'

whereas the below works:

filtersManager.configure();
filtersManager.process();
Riata answered 17/2, 2014 at 8:51 Comment(6)
The IIFE has no context, this depends on how you call a function. this inside each function is already the object.Frankfrankalmoign
I tried with "this" and it worked but I'd like to avoid using "this" directly. In case, the method is also called from another private function within the class which changes the context.Riata
}(jQuery)); is this correct closing isn't it should be })(jQuery); this way.Gusgusba
@Gusgusba Yes but the former is the preferred.Slyke
@Jai: It's valid, just semantics. }(jQuery)) in fact makes more sense, as the function is being called and wrapped in parenthesis to force an expression.Frankfrankalmoign
bit late to the party here but, at the result is being assigned to filtersManager it's forced to be an expression, the function doesn't need extra parenthesis :-) : filtersManager = function ($) { ... }(jQuery);Kaiulani
S
15

You are returning the wrong thing (this in a plain function invocation is the global object). You want to return the object that you originally created, which I will call the interface.

filtersManager = (function ($) {

    var interface = {
        // public functions
        configure: configure,
        process: process
    };

    function configure() {

        // some work

        return interface;
    };

    function process() {

       // some work

        return interface;
    }    

    return interface;
}(jQuery));

If you're wondering why I can reference the functions defined below, it's due to hoisting.

Spic answered 17/2, 2014 at 8:53 Comment(1)
Still one of my favourite and most flexible js patterns.Blancmange
W
2

Immediate function is executed in global object (window) context. Try something similar to this:

filtersManager = (function ($) {

    var that = {};

    that.configure = function() {
        // some work
        return that;
    };

    that.process = function() {
        // some work
        return that;
    }

    return that;

}(jQuery));


UPD. Based on comments

Constructor pattern seems to fit your need better:

var FiltersManager = (function($) {

    function FiltersManager() {}

    FiltersManager.prototype = {
        configure: function() {
            console.log('configure');
            return this;
        },
        process: function() {
            console.log('process');
            return this;
        }
    }

    return FiltersManager;

}(jQuery));

new FiltersManager().configure().process();
Wommera answered 17/2, 2014 at 8:55 Comment(3)
hmm, isn't {} an empty object. It doesn't necessarily reflect the same object.Riata
@TheLight What do you mean?Wommera
I mean P{ creates a new empty object whereas I'd like to refer to the same filtersManager object.Riata
S
0

As to continue what others have said , I think you confused with the function constructor syntax which would work , similar to what you've said ;

var G=function g()
{
  this.configure =function (){return this;}
  this.process  =function (){return this;}
};

var _= new G();




console.log(_.configure().process())
Slyke answered 17/2, 2014 at 8:57 Comment(2)
That'd work, but I think it'd be better placing those methods on the prototype.Spic
@Spic Agree . Just want to point it out that there are other method too which looked alike his basic syntaxSlyke
K
0

If you wanted to re-use the functions on other objects too, you could do it like this

filtersManager = function ($) {

    function configure() {

        // some work

        return this;
    };

    function process() {

       // some work

        return this;
    }    

    return {
        // public functions
        configure: configure,
        process: process
    };
}(jQuery);

(OTOH, if you wanted to create aliases to them, you would then have to bind them to the object)

Or if configure and process are quite short, simple functions :

filtersManager = (function ($) {

    return {
      
        // public functions
        configure: function () {

            // some work

            return this;
        },
      
        process: function () {

           // some work

            return this;
        }
    };
}(jQuery));
Kaiulani answered 24/7, 2015 at 8:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.