

The jQuery Divide:Understand where jQuery ends and JavaScript begins - binarray2000
http://www.slideshare.net/rmurphey/the-jquery-divide-5287573

======
troels
I'm not so sure I buy the premise that jquery is unsuitable for large scale
applications. I think it is based on an assumption that jquery should provide
a framework for these things, but really - what jquery is, is a framework for
the controller layer of an application. If you want to use it, you have to
provide the model level framework your self. I don't think this is the fault
of jquery anymore than it would be the fault of Sinatra.rb to not provide the
functionality of Rails.

~~~
aristus
jQuery as commonly used leads, in my personal experience, to hard-to-maintain
programs. Just like Ruby on Rails, or Perl.

There is also anecdotal evidence that jQuery qua jQuery has some fundamental
limits. I worked on a largish jQuery application, written by ninja badasses,
and it creaked a lot more than it should have for its size.

Comparable systems built on YUI seemed to have more structure. I actually went
through the exercise of converting a prototype from jQuery to YUI3, and spent
a lot of time working out their respective "philosophies". (see
<http://jsrosettastone.com>)

There are newer frameworks (eg JavelinJS) that aim to be to jQuery what jQuery
was to other frameworks.

~~~
bad_user

        I worked on a largish jQuery application, 
        written by ninja badasses
    

I don't think those " _ninja badasses_ " were as good as you're describing
them.

If they were, they would realize that jQuery is not a framework that
structures your application, but just a neat and light library that provides
syntactic sugar for DOM-manipulation + dealing with cross-browser issues.

    
    
        jQuery as commonly used leads, in my personal 
        experience, to hard-to-maintain programs. Just
        like Ruby on Rails, or Perl.
    

Well, I could say the same thing about Java/C# or PHP ... in fact, the shit I
had to put up with in those (more structured) platforms is far worse than
anything I have seen thus far that was done on top of jQuery / Rails and Perl.
And I thought Python/Django had immunity from such problems, until a month
ago.

Newsflash: bad developers write bad code.

And yes, I've worked with Perl -- Catalyst and DBIx::Class are pretty good,
you should check them out ;-)

~~~
aristus
Well, you may have a different experience.

I've also noticed a new trend in complex applications, eg JavelinJS and
Yahoo's "Minty" mail app, that moves away from jQuery's or YUI's model. They
feature a centralized controller/arbiter and a separation of CSS classes and
event markup. Instead of jQuery + MVC it's a little of both.

See also <http://news.ycombinator.com/item?id=2430271>

------
krosaen
IMHO the most important "clean code" boundary for web apps is a non-enhanced
interface (plain old forms). From there, pages can progressively enhance until
the cows come home with jquery plugins and complicated interface code, but as
long as you know it boils down to a form submission, it's easy to understand
what is going on in the application. The form is the model into your web app,
and everything else is just sugar.

And whether working on an android app, a QT application in C++ or a jquery
based rich client interface, rich client functionality is always somewhat
messy in my experience by nature of having many complex interactions in a
stateful environment. I certainly don't see using YUI as a silver bullet to
alleviate the complexity. As long as it is always clear where the boundaries
between the communication between the client code and the server / and its
model, you will maintain a clean and maintainable core.

If you want to ditch the idea of progressive enhancement and work directly
with a web api to your server, then similar rules apply; as long as it is
clear that "this page / widget presents a snazzy interface to update this
model" you can remain sane in the organization of your app.

Finally, if you have a super rich interface like Asana, pivotal tracker or
google wave where the entire page is presenting many models at once in many
forms, then a functional reactive approach may help, using something like
backbone or what luna script promises to be. But using a framework like that
has its own cost and complexity and IMO is overkill for many of the web apps
out there.

------
joetyson
I don't see it mentioned very often, but google's closure-library has some
really phenomenal patterns for building maintainable javascript. Its worth
checking out Michael Bolin's book, Closure: The Definitive Guide, which goes
in depth of the Component and Control frameworks.

I've been using the library for 2 or 3 years now, and I am always surprised to
see it has such a small community.

~~~
qusiba
Exactly. I see closure as an ambitious effort to make JavaScript a better
language for real complicate applications.

------
ichilton
Here is a video of the talk you refer to:
<http://jsconfeu.blip.tv/file/4308069/>

------
perlgeek
So, how does one become a good, non-spaghetti-code javascript developer for
the web?

I don't really like js so far, but there are just no alternatives in some
cases. And my code ends up like those counter examples. Where can learn how to
organize it properly?

~~~
DanielRibeiro
No alternatives? Coffeescript is always an alternative to js:
<http://jashkenas.github.com/coffee-script/>

~~~
bcrescimanno
Coffeescript "compiles" to JS--so it's not an alternative to using Javascript;
just an alternative syntax for writing javascript.

~~~
DanielRibeiro
Coffeescript is a different language though. It has different grammar,
different keywords and so on. It shares the same object model, and it is
usually used on compile form.

There are other alternatives as well[1], such as:

\- LLVM languages: <http://syntensity.blogspot.com/2011/04/emscripten-10.html>

\- HotRuby: <http://hotruby.yukoba.jp/>

\- Smalltalk: <http://clamato.net/>

\- Haxe: <http://haxe.org/>

\- Mascara: <http://www.mascaraengine.com/>

And so on. Coffeescript is just closer to javascript than most alternatives.
But it is a different language, and a nicer one in my humble opinion.

[1] [https://github.com/jashkenas/coffee-script/wiki/List-of-
lang...](https://github.com/jashkenas/coffee-script/wiki/List-of-languages-
that-compile-to-JS)

~~~
bcrescimanno
I disagree that any language that "compiles" into another language can be
considered an "alternative." I'm not bashing CoffeeScript; I haven't played
with it much and don't know enough about it say anything one way or the other;
but at the end of the day, the result is still Javascript.

------
nezumi
Hey! That's exactly how my jQuery code looks! I think I just got seduced by
all the closurey goodness that comes with Javascript (my day-job languages
don't let me do that.)

I'm not going to ask how to write good code, but I think this is a fair
question: can someone point to a coding standard / style guideline for
Javascript + jQuery?

E.g., when to choose a single-use named function over an anonymous function?
When to bind jQuery results to variables vs. go crazy with chaining? Any
advice on good selector practices? Good html naming conventions?

I'd love to see all that stuff documented in one place. It must be out there
somewhere.

~~~
irahul
> can someone point to a coding standard / style guideline for Javascript +
> jQuery?

backbone.js is good. That gives you a fair idea about structuring your
application. If you webapp is designed in a RESTful manner, backbone.js maps
quite nicely to your backend.

------
emehrkay
People at my job call all JavaScript jQuery, it is so annoying. Even more
annoying is that their code (jQuery or not) plain sucks

~~~
emehrkay
When I use jQuery (MooTools is my lib of choice) I find myself using it in
ways that is very unlike the majority of jQuery that is seen around the web.

I absolutely hate the plugin system simply because you cannot easily get the
instance of the plugin an refer to it later. To answer this I use function
constructors with the module pattern (its easy and doesnt require an extra lib
to get going) to create my plugins. Another thing that I do is when I query
for a collection of objects, create an array that represents every item in
that collection already wrapped with the jQuery object. This may not seem like
a big deal, but there is a difference between

    
    
        var collection = jQuery('a');
        collection.each(function(i, l){
            var link = jQuery(l);
            link.bind('click', function(){//do suff});
        });
    

and

    
    
        var collection = jQuery('a'),
            collected = (function(){
                var c = [];
                $.each(collection, function(i, item){
                    c.push(jQuery(item));
                });
                return c;
            })();
    

this second way allows you to select an item from collected without having to
rewrap it with the jquery object. I dont have any data on it, but it seems
like rerunning jQuery() with every mouseover/mouseleave/event etc seems like a
waste of processing.

Anyway, that is just a few ways that I use jQuery to make javascript a bit
easier. These little tricks have the people that I work with thinking that I'm
some sort of genius.

~~~
arethuza
Isn't that second code snippet actually creating a jQuery object for each "a"
- even if it is never clicked on? Isn't that rather more of a "waste of
processing" than the first, where a jQuery object is created in the event
handler?

Why wouldn't you write the first one as:

    
    
       $("a").click(function() { // do stuff });

~~~
emehrkay
if you need to do stuff with a inside of the function, then you have to do
$(this), so every time an a in that collection is clicked $() is run.

In my first example I actually took that problem out of the equation by
looping through the collection and storing the jQuery'd a as a var accessible
via the event closure. However, if you want to reference an element in that
collection later in your code, you have to jump though the jQuery selection
hoops.

But you are right, sometimes you may not need to have every element in your
selection wrapped in the jQuery object and it is up to you to determine which
solution to use in a given case. But I do feel that most cases I see devs
constantly wrapping $(this) inside of event handlers when they could have made
an external reference/collection before hand and used that.

    
    
        $('a').hover(
            function(e){
               $(this).doSomething();
            },
            function(e){
               $(this).doSomething();
            }
        );
    

vs

    
    
        var as = $('a'),
            collected //using the same method as above;
    
        as.each(function(i, e){
           collected[i].hover(
                function(e){
                    collected[i].doSomething();
                },
                function(e){
                   collected[i].doSomething();
                }
          );
        );
    

This is a very rudimentary example and I know that there is a simpler way to
accomplish this, but imagine code with multiple collected items who all match
up on a 1 to 1 basis collecting the pre-wrapped objects has its advantages.

~~~
xtian
But wouldn't multiple potentially long loops on initial load have a greater
possible impact on user experience than one extra call to $() per event?

~~~
emehrkay
Great point. I think that my simplistic example is just that, simplistic. A
better solution for huge collections would be to memoize the retrieval of the
$() obj with something like

    
    
        var memd = {},
            getMem = function(obj){
               var o;
               if(memd[obj]){
                  o = memd[obj];
               }else{
                  o = memd[obj] = $(obj);
                }
               return o;
             };
    

and call that function instead of calling $() while inside of an event handler
(I havent tested this code, but the concept is straight forward)

~~~
arethuza
I don't want to appear snarky, but as you admit yourself ("I dont have any
data on it") you don't know if creating a jQuery object is expensive or not
(to be fair, I don't know either) - so why all the extra complexity if you
don't know whether the thing you are trying to avoid (creating instance of
jQuery during event handlers) actually causes problems or not?

~~~
emehrkay
Well given that a lot of the "pro" jQuery tips say that one should avoid
rerunning the selector in favor of some sort of memoization:

    
    
        $('.class').doSomehting();
        $('.class').doSomethingElse();
        $('.class').thirdThing();
    

in favor of

    
    
        var ele = $('.class');
        ele.doSomething();
        ele.doSomethingElse();
        ele.thirdThing();
    

I would only assume that re-querying with the jQuery object inside of event
handlers has the same adverse effects.

Lets say you have a very simple tabbed thing

    
    
        //this is code that i've seen around
        var tabs = $('a.tab'),
            containers = $('div.container');
            
        tabs.click(function(e){
            var index = tabs.indexOf($(this));
            tabs.removeClass('active');
            $(this).addClass('active');
            containers.css('display', 'none');
            $(containers[index]).css('display', 'block'); 
        });
        

vs //this is how id handle a simple tabber var tabs = $('a.tab'), containers =
$('div.container'), all_containers = $.map(containers, function(i, c){ return
$(c); });

    
    
        $.each(all_tabs, function(i, tab){
            var t = $(tab);
            
            t.bind('click', function(e){
                tabs.removeClass('active');
                t.addClass('active');
                containers.css('display', 'none');
                all_containers[i].css('display', 'block');
            });
        });
    

I just feel that the first one, while more concise (has it obvious areas of
improvement, but general idea) would wind up being more expensive than the
second.

If running the jQuery object isnt too expensive, why is the practice of
rerunning the same selector frowned upon?

~~~
xtian
Interacting with the DOM is what's slow. It's especially slow if the native
querySelectorAll method isn't available because any non-trivial selections
necessitate iterating over the DOM tree. That's why you don't want to re-query
a selection multiple times.

That's also why it's recommended that all selections start with an id. The
size of the tree to iterate over can be quickly reduced using the native
getElementByID method.

In the case of $(this), the DOM node is already passed to the event handler,
so wrapping it in a jQuery object doesn't touch the DOM tree at all.
Furthermore, I always cache it (var $this = $(this);) if I'm going to use it
more than once.

Also, in your first example, you don't have to rewrap containers[index] in a
jQuery object. All the elements in the selection are already wrapped.

~~~
emehrkay
> Also, in your first example, you don't have to rewrap containers[index] in a
> jQuery object. All the elements in the selection are already wrapped.

Really? I think that is the whole point of this long comment thread -- that
the elements in a collection arent already wrapped.

<http://jsfiddle.net/8nqtA/>

This doesnt work unless i wrap a[i] in $()

But like you're saying, it may be fruitless since the dom is the bottleneck
and we're bypassing it by already having the element.

~~~
M1573RMU74710N
Well there's a few problems with that example:

1) You've got a "global" named a and then a local variable (via the argument)
inside the each function called "a"...so that really confuses things.

2) a[i] where a is a jQuery object returns an unwrapped DOM element...what you
want is .index().

3) What you're doing is sort of roundabout...

Why not:

    
    
        var d = $('div'),
            a = $('a');
    
        a.each(function(i, el){
             d.text(d.text() +' '+ $(this).text() );
        });
    
    

Or if you really want to do it your way:

    
    
        var d = $('div'),
            a = $('a');
    
        a.each(function(i, el){
             d.text(d.text() +' '+ a.index(i).text() );
        });

~~~
arethuza
Shouldn't the second one be:

    
    
        var d = $('div'),
            a = $('a');
    
        a.each(function(i, el){
             d.text(d.text() +' '+ a.eq(i).text() );
        });
    

Using eq(i) rather than index(i)?

~~~
emehrkay
I feel like this should have been the first replay to my rant. The nodes are
already wrapped in the jQuery object, just need to use eq to access them by
index. I've never seen that before, thanks

~~~
xtian
They actually aren't already wrapped. The .eq() method pulls an element out of
the collection and wraps it in a new jQuery object.

------
jokull
I was hoping for a Backbone.js mention. A tool like that will get you a long
way in structuring your frontend code.

~~~
rmurphey3
Backbone.js came out just a couple of weeks before I gave this talk in October
2010, and I just hadn't had time to look at it enough to feel comfortable
mentioning it. It is definitely a powerful tool for bringing structure to an
application, and I'd certainly mention it if I were to give the talk today.

------
rodh257
I don't like presentations like this. What suggestions or solutions were
offered? Perhaps the audio mentioned some good resources to use to learn how
to properly architect a complex, Javascript/JQuery heavy application, or
perhaps I just missed it in the slides, but to me it just seemed like a rant.
Sure it's identifying an issue but it would be a whole lot more useful if it
gave some links to books/articles/etc with details on how to layout your code
in a maintainable manner.

~~~
rmurphey3
I'd encourage you to bear in mind the original audience of the presentation:
the very small number of experienced JavaScript developers who managed to
obtain a ticket to the 2010 JSConf.eu in Berlin.

The goal of this presentation wasn't to teach people how to write good
JavaScript -- many of the people in the room that day can and do write circles
around me. Rather, the goal was to urge them, the experienced JS devs who are
inventing the answers to these questions, to take seriously the need for
creating exactly the information you point out to be lacking, and to be
intellectually rigorous and honest in discussions of various solutions.

I'd suggest that you pay extra attention to the presentation starting at slide
40, and especially to what I said on slide 60: "Sharing what we know is as
important as making new things." That, in a nutshell, was the message I sought
to convey to the audience in October.

------
Fluxx
jQuery is popular because you don't need _any_ programming experience to be
productive. I was introduced to jQuery by our in-house web _designer_ like 3
years ago because he used it and really liked it. He spoke HTML, the DOM and
CSS and so does jQuery. And there are far more HTML/CSS literate people doing
Javascript than there are CS-educated software engineers doing Javascript. In
fact most software engineers I know don't know crap about Javascript.
Thankfully I read "Javascript: The Good Parts" and have a much better
appreciation for the language.

I also like jQuery as well. If you're doing simple DOM manipulation, AJAX and
light javascript work it's hard to do any better. But I think there are
superior choices for some more heavy lifting JS projects.

------
mcdaid
Nice presentation, I am not sure about most people here but I started using
jQuery because the documentation was excellent, easy to navigate, with lots of
examples. Hence trying it out was simple and I got hooked.

At that time IMO the other libraries apart from YUI, did not seem to have
everything in place to learn how to use them quickly. I was put off YUI at the
time because it seemed incredibly verbose, this has since been improved.

Also I think a distinction can be made between using jQuery and using the
widget factory which does allow for more modular maintainable code.

------
chopsueyar
Maybe the MVC design pattern doesn't work so well with jQuery in the view,
acting as a controller and also for display logic.

Surely there is a design pattern that does not try to shoehorn AJAX via jQuery
into what was once an MVC pattern?

MVC for webapps was around long before AJAX, yet the design pattern remained
the same, after the widespread introduction of AJAX in webapps. Until very
recently, there has been little traction in an 'evolved' design pattern,
incorporating what the js is doing.

------
robfig
Since no particular solutions were offered in the talk...

HN: What are the best technologies for writing large JS apps?

I have experience writing Closure (<http://code.google.com/closure/>) and its
structure is pretty scalable, but it feels like so much effort to do simple
things. Styling the widgets is a pain. Making a custom widget (extending
goog.ui.Component) is surprisingly difficult to get right for even simple
extensions.

After all that, I still think it's probably better to develop in that over
jQuery -- at least you end up with a straightforward, modular, testable
structure at the end of the day.

Is there something better? backbone?

------
OzzyB
About time someone came out and said this, good job.

~~~
ars
Said what? Did I miss it? He seemed to just stop midway.

He implied there was a problem, showed some code, but never showed where the
problem lies or what it was, and certainly never mentioned any solution.

All I got was some vague "this isn't pretty" vibes.

~~~
rmurphey3
I can't speak to what else you missed or didn't miss, but you do seem to have
missed that he is a she, so ...

~~~
rodh257
doesn't change the original point

