3

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);
            });
        };
    });
} ());
Community
  • 1
  • 1
Alex Dn
  • 5,465
  • 7
  • 41
  • 79
  • 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`). – Bergi Jul 25 '13 at 20:33
  • @Bergi i added the example - this is really works, the code already passed QA stage :) – Alex Dn Jul 25 '13 at 20:37
  • Inside of any object you should be able to get access to `this` which reefers to the current object. – travis Jul 25 '13 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 :) – Alex Dn Jul 25 '13 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. – Bergi Jul 25 '13 at 20:49
  • @Bergi, hm...actually, right now it single instance, but there can be other types with multiple instance...actually I didn't test it with multiple instances of the same class :) QA just tested the process that I work on, not the JS implementation...so I will wait with fire them :)) – Alex Dn Jul 25 '13 at 20:52
  • @AlexDn I see that, define `$this` inside of init then. http://jsfiddle.net/qxJXS/ – travis Jul 25 '13 at 20:56
  • @travis I started from it, but in that way, only init will have $this and then I still have problem with "this" in other methods :( – Alex Dn Jul 25 '13 at 20:59
  • Ya, it would have to be the first line of ever function. I hardly see that as a problem, that's the natural of the language. Even with Rafael Gomes answer, your still going to have to save the current scope if you want to access anything inside of `this`. – travis Jul 25 '13 at 21:06
  • @travis yep, it looks like if I will not find another solution I will go with this, bit it very sad :( – Alex Dn Jul 25 '13 at 21:11

2 Answers2

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
Rafael Gomes
  • 112
  • 1
  • 9
  • It looks nice, but what about inheritance? How in your pattern I can create MySecondModule that inherits from NameOfYourModule? Class gives it for me. – Alex Dn Jul 25 '13 at 20:47
  • I added reference exaplaining how it works inheritance. Glad to help :) – Rafael Gomes Jul 25 '13 at 20:53
  • 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... – Alex Dn Jul 25 '13 at 20:56
  • 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 ;) – Rafael Gomes Jul 25 '13 at 20:58
  • I agree that learning new patterns and improve the knowledge is very good thing, but unfortunately it all depends of the "team quality" and if I will create something more "complex" that the team member want to use, instead of learning they will not use it :(( – Alex Dn Jul 25 '13 at 21:01
  • I agree with you... but you can raise your "team quality" ;) – Rafael Gomes Jul 25 '13 at 21:06
  • 1
    @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! – Bergi Jul 25 '13 at 21:21
  • I'd like to show how to create OOP using class, but it can be done too with some adjustments. I like this way :) Is there a problem for you, do u see some improvements? I'm always open to discuss. Thanks @Bergi – Rafael Gomes Jul 25 '13 at 21:30
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);
    }
});
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 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 :) – Alex Dn Jul 25 '13 at 21:35
  • Can you point me please, to a good pattern how to create a "module" that need to be initialized with data on creation? – Alex Dn Jul 25 '13 at 21:42
  • 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. – Bergi Jul 25 '13 at 21:49