2

I'm using John Resig's simple OOP Class that is adapted to use "use strict" and taken from SO post.
In all examples I see the usage of Class.extend like so:

var MyObj = Class.extend({
    init:function(){},
    prop: "Property"
});

But I found a large disadvantage for me of using it in such way - I cannot have "private" variables, so I cannot store reference to this like var $this = this;. I found the solution for my case, and now I using the Class.extend in following way:

var MyObj = Class.extend(new function(){
    var $this = this;
    this.init = function(){};
    this.prop = "Property";
});

Everything works in my case, but I want to know if there some things that can cause me problems in a long run?
Does this way my application will consume much more memory in browser?
What alternative ways I have to implement my needs?

Note: I need to store $this, because I use heavily events and callbacks, so I want to refer "original" this easy to have access to all methods and properties on object.

EDIT: As requested, this is my code example:

(function () {
    "use strict";
    window.QuickPlay = Class.extend(new function () {
        var $this = this;

        this.init = function (initData) {
            $this.elementsToHide.push(initData.el);
            $(function () {
                playProcessStart();
                Sys.Application.add_load(function () {
                    $find("ctl00_ContentPlaceHolderMain_ctrlPlayPopup1").add_closed(function () { $this.setElementsVisibility(""); });
                });
                $this.setElementsVisibility("hidden");
            });
        };

        this.elementsToHide = [];

        this.setElementsVisibility = function (visibility) {
            $.each($this.elementsToHide, function (i) {
                $("#" + this).css("visibility", visibility);
            });
        };
    });
} ());
10
  • 3
    Ouch, no. I hardly can believe this really works for you. Please show us how you are using this "class" with events and callbacks; maybe post your actual code (at least the methods that involve $this). Commented Jul 25, 2013 at 20:33
  • @Bergi i added the example - this is really works, the code already passed QA stage :) Commented Jul 25, 2013 at 20:37
  • Inside of any object you should be able to get access to this which reefers to the current object. Commented Jul 25, 2013 at 20:46
  • @travis if you see, on jQuery document ready, I'm using $this, because if I will use this, it will not reference an instance of QuickPlay :) Commented Jul 25, 2013 at 20:48
  • Then fire the QA team :-/ To see it break, you could try to make multiple instances. Or is it supposed to be a singleton? Then you shouldn't use Class at all. Commented Jul 25, 2013 at 20:49

2 Answers 2

2

You can use module pattern and maintain all the OOP. These kind of pattern gives your code more security and better organization.

//these are namespaces in javascript
window.project = window.project || {}; //this kind declarations prevents recreate the object
project.group = project.group || {};

//in the line below we can use $ instead jQuery, and use window and document instead ask for the browser every time.
(function (window, document, $) {
    "use strict";

    project.group.NameOfYourModule = function () {
        var privateAttribute = true,
            students = 32,    //It's is a best practice declare everything in an unique var.

            privateMethod = function () {
                alert('Now I know OOP using jQuery');
            };

        return {
            init: function () {
                //this is a public method and we can initiate some private method;
                privateMethod();

                //we call a public method using this
                this.publicMethod();
            },
            publicMethod: function () {
                //this is a public method
            }
        };
    };

    $(function () {
        var myclass = new project.group.NameOfYourModule(); //instantiate you class
        myclass.init(); //initiate some public method
    });
}(window, document, jQuery));
  • Working example at JsFiddle
  • How to work with Inheritance and Module Pattern here
Sign up to request clarification or add additional context in comments.

8 Comments

It looks nice, but what about inheritance? How in your pattern I can create MySecondModule that inherits from NameOfYourModule? Class gives it for me.
I added reference exaplaining how it works inheritance. Glad to help :)
Thanks, I saw the link...I'm sure it will work, but it too complex for other team members :( I'm trying something that easy to use...
In my company we use this kind of pattern, maintain the organization and prevent some problems in the future. Why not gain some time learning more complex patterns? In the future maybe you have problems with organization and will have to refactore all you code. Think about that :) It's not that complex, I swear ;)
@RafaelGomes: What you have there doesn't look like a (singleton) module, more like a class. You wouldn't make it instantiable, but create it in an IEFE. And remove the new keyword, you're simply returning an object from the factory not invoking a constructor!
|
1

I cannot have "private" variables

Of course you can. Either in the (currently unnecessary) (function () { … } ()); wrapper, or in your constructor (the init thing).

new function () {

Avoid that pattern! If you really need your code to work as it does now, use

(function () {
    "use strict";
    // Here's the place where you could put a private, static variable
    // for example `var elementsToHide = [];`
    var $this = {
        init: function (initData) {
            $this.elementsToHide.push(initData.el);
            $(function () {
                playProcessStart();
                Sys.Application.add_load(function () {
                    $find("ctl00_ContentPlaceHolderMain_ctrlPlayPopup1").add_closed(function () {
                        $this.setElementsVisibility("");
                    });
                });
                $this.setElementsVisibility("hidden");
            });
        },
        elementsToHide: [],
        setElementsVisibility: function (visibility) {
            $.each($this.elementsToHide, function (i) {
                $("#" + this).css("visibility", visibility);
            });
        }
    };
    window.QuickPlay = Class.extend($this);
}());

I want to know if there are some things that can cause me problems

Yes. Multiple instances will hardly work, as they all do reference the same elementsToHide array. And you're not using any instance methods at (only a constructor and static elements on your class), so the class pattern seems quite unnecessary. Use a module instead. If you need single instances (and classes), the code should look like this:

"use strict";

window.QuickPlay = Class.extend({
    init: function (initData) {
        var $this = this;
        this.elementsToHide = [];
        $(function () {
            playProcessStart();
            $this.elementsToHide.push(document.getElementById(initData.el));
            Sys.Application.add_load(function () {
                $find("ctl00_ContentPlaceHolderMain_ctrlPlayPopup1").add_closed(function () {
                    $this.setElementsVisibility("");
                });
            });
            $this.setElementsVisibility("hidden");
        });
    },
    setElementsVisibility: function (visibility) {
        $(this.elementsToHide).css("visibility", visibility);
    }
});

3 Comments

Thank you for pointing me to the "huge" problem in a way I use Class...In my application I will need to use "singletons" and Classes to, so it looks like I will need to use/create two different patterns for each of cases. Currently I just started with JS OOP in project, so it's not too late to change the things yet :)
Can you point me please, to a good pattern how to create a "module" that need to be initialized with data on creation?
I would think of a singleton module as quite static, without "creation". I could think of a) the data is coded into the module code b) the module fetches the data itself from the global "data store" c) the global controller "starts" the module by calling the init method with the data as arguments. See Osmani's article which I've linked for code structure patterns.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.