0

Ok I am definitely learning a lot when it comes to JavaScript scope functions and module patterns, awesome stuff! Right now I'm teaching myself to pass jQuery into a scope function this way it loads sooner, and if for some reason I had another framework that used $, there will be no confusion.

But what I don't fully understand is when to create a "new" instance "in context to scope functions" when I want to pass in jQuery. Here is what I mean...If I was going to use the following as a base, it will return pubs, which can be associated to a function or properties, etc, I get it.

var DemoA = (function($) {
var pubs = {};
pubs.dosomething = //some function that calculates cool stuff with help of jquery
return pubs;
})(jQuery);

Now when I try to create a new instance....

var stuff = new DemoA();

...I get an error through Google Chrome Developer Tools. It says "object is not a function" or something to that effect. But if I call DemoA directly like this...

DemoA.dosomething();

...then everything works fine. What is going on here? and why can't I create a new instance variable?

Thanks in advance for helping me get smarter!

klewis
  • 7,459
  • 15
  • 58
  • 102

2 Answers2

5

Look at your return statement. You're returning an object that looks like this:

{"dosomething": function () { }}

You can't create a new instance of an object. You can call dosomething directly because it's an immediate property (method) of the returned object.

I think you want something like this:

http://jsfiddle.net/veJqg/

var DemoA = (function($) {
    var pubs = function () {
        this.dosomething = function () {
            console.log("just executed `dosomething`");
        };
    };
    return pubs;
})(jQuery);

var a = new DemoA();
a.dosomething();

This way, you are still aliasing the jQuery object as $, and you are returning a function that can be used in the way you want.

Ian
  • 50,146
  • 13
  • 101
  • 111
  • Using a closure just to store a variable that could be passed to the instance or just referenced or "aliased" as `$=jQuery` seems inappropriate. – RobG Oct 18 '12 at 23:16
  • @RobG How is that inappropriate? It's fairly common when creating a jQuery plugin, mainly to make sure it works even if there's another library like Prototype that uses `$` as its identifier – Ian Oct 18 '12 at 23:22
  • Because it's creating a closure where there's no need for one. Simply assigning `var $ = jQuery` in the function does the same thing without the closure. Just because something is common doesn't make it suitable in a particular case. – RobG Oct 19 '12 at 02:03
  • @RobG Then why do jQuery plugins do it? Why wouldn't they just do what you're saying? – Ian Oct 19 '12 at 02:04
  • If they took the time to evaluate their particular circumstance and understand the options and consequences, then chose the most appropriate approach perhaps there would be a greater variety of approaches. But I suspect they just do what everyone else does (or the [jQuery documentation instructs](http://docs.jquery.com/Plugins/Authoring#Getting_Started) without justification for "best"), then claim the [bovine defence](http://en.wikipedia.org/wiki/Herd_mentality) (or [*argumentum ad populum*](http://en.wikipedia.org/wiki/Argumentum_ad_populum) if you like fancy names) of "best practice". – RobG Oct 19 '12 at 03:02
  • @RobG I'm sure it has to do with the fact that it's easier to use a closure than doing something like `var old_$ = $; $ = jQuery; /* code */ $ = old_$;` – Ian Oct 19 '12 at 03:24
  • `(function(){var $=jQuery;...}())` is effectively identical to `(function($){...}(jQuery))` and more obvious. For functions in the IIFE, `var $ = jQuery` anywhere will have the same effect. There is no need set/reset *old_$*. I'm not saying it should always or only be used, only that it's more appropriate in some (perhaps many) cases to avoid an unnecessary closure. – RobG Oct 19 '12 at 03:39
  • @RobG I see what you're saying for your first sentence - I wonder if there's a reason why it's better/worse to pass it as a parameter or just redeclare `$` as you say. The reason why you "need" to use the whole `old_$` thing is in case `$` is something else than jQuery - like Prototype. In that case, you "need" `$` to reference jQuery in the targeted code, but for the rest of the code, it should stay as a reference to Prototype. Does that make sense? – Ian Oct 19 '12 at 04:25
  • As far as performance goes, is it always good practice to reference all of our private methods into one contructor function and return that single constructor? Even if we have 10+ private methods? Or would we get better performance in calling individual methods only when we need them? i.e. Not storing everything into one single constructor function, but returning multiple methods. Not looking for demo, just ideas on the topic - thanks. – klewis Oct 19 '12 at 11:26
0

Just a bit more complex jQuery example which is commonly used:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
(function($) {

  $.DemoA = function(element, options) {
    var pubs = {};
    return pubs;
  }

  $.fn.DemoA = function(options) {
     return this.each(function() {
       (new $.DemoA($(this), options));
     });
   };

})(jQuery);

var i = new $.DemoA(item, {});
var j = $('<div>').DemoA();
</script>
Reflective
  • 3,854
  • 1
  • 13
  • 25