From jQuery to JavaScript and back again
benhowdle.im
benhowdle.im
I'm not aware of any JS.next-type efforts to do this though :(
I think that the problems with JavaScript are very obvious to developers who have used multiple languages (aside from PHP). There are far too many unacceptable quirks. It is full of absolutely stupid ideas, like semicolon insertion. Its scoping is poorly designed. In practice, prototype-based OO is inferior to class-based OO. Its type system is not sensible. It lacks proper support for namespacing and modularity (sorry, CommonJS is a hack and nothing more). It does not have a practical standard library. Its development environments and debuggers are quite lacking. And these are just some of its numerous issues.
So for such a small language, it has many critical flaws. This situation is far worse than what we see when dealing with most other languages. And none of those problems that are listed above have to do with the DOM, so disregarding it has absolutely no impact on them.
Actually its scoping is very well defined: javascript has function scoping and a global scope. That's it.
> In practice, prototype-based OO is inferior to class-based OO.
That is plain and simply not true. A shitty object model is inferior to a good object model, but that's got nothing to do with prototypes v classes (as far as I'm concerned, the world would probably be a lot more enjoyable if more language implemented a self-like object model).
> Its development environments and debuggers are quite lacking.
They're already ahead of most non-corporate languages and keep improving at a fast pace.
And ES6 adds block scopes (via `let`, inherited from Mozilla's javascript extensions).
That strays from the original complaint though.
Class-based OO is implementable with prototype-based OO (with some exceptions such as "protected" which are mostly unnecessary when first class functions are available). In practice, this means you need to learn how to use it (unfortunately the quirky way its implemented in JS doesn't help this at all)
CommonJS provides quite excellent namespacing and modularity - its only a hack because it doesn't work in browsers [2]
The standard library is admittedly lacking but there are many libraries that cover this gap, some of them being de facto standard.
Development environment support is pretty good for a dynamic language, with multiple IDEs doing some form of static analysis and completion
Debugging is pretty good, with modern browsers supporting breakpoints, watch expressions, live code editing, logging with object inspection etc. For node you have the v8 debugger and node-inspector providing pretty much the same.
There are far more pressing issues with JS than the ones you mentioned, like the verbose function syntax (mostly fixed in Harmony), lack of coroutines (mostly fixed with Harmony generators), lack of something like ruby's method_missing or python's __getattr__ (fixed with Harmony proxies)...
[1]: an example of a major deal breaker is not having first class functions
[2]: actually, it kind-of does - https://github.com/substack/node-browserify https://github.com/azer/onejs etc.
[1] http://caniuse.com/queryselector [2] http://sizzlejs.com/
They provide a limited part of the selection function. Altering nodes, creating new nodes (and adding them to the DOM tree) and programmatic DOM tree traversals? Not so much, you get very clumsy and verbose APIs for that in the regular DOM. Same with DOM event handling, jQuery provides nice shortcuts for binding and delegation, the DOM... not so much (even if you limit yourself to IE9 and don't have to handle the garbage that is the oldIE event model)
Also, as usual with the fucking DOM, querySelectorAll returns a NodeList which means you can't trivially use higher-order iterators on it (you've got to use the "generics" version and hope it works correctly everywhere).
Fuck, that makes me angry again, the DOM is such a clusterfuck of an API.
Array.prototype.forEach.call(
document.querySelectorAll('a'), function(el){
console.log(el);
});
But, I agree with the point. If the NodeList isn't live, like it is for the other DOM querying methods, then what is the point in returning a NodeList instead of an array?This is not something you should use in production, but just a quick example:
function setAttr (attr, val) {
return function (elem) { elem.setAttribute(attr, val); };
}
NodeList.prototype.forEach = Array.prototype.forEach;
var $ = document.querySelectorAll.bind(document);
$('.foo').forEach(setAttr('foo', 'bar'));[0] https://github.com/jquery/jquery/blob/master/README.md [1] http://yuilibrary.com/yui/configurator/
[edited with better link to JQuery build documentation]
Your quick example is risky and likely broken to all MSIE <= 8: https://developer.mozilla.org/en-US/docs/DOM/NodeList#Why_ca...
I don't understand why people want to make a distinction between vanilla JS and jQuery. It's like saying you want to make a distinction between standard C++ and QT. One is a language, the other is an interface. jQuery doesn't exactly provide a standard library by any stretch of the imagination.
So that's the point that OP is making. First learn JavaScript, then move to abstractions such as jQuery. That way you won't ask silly questions such as "how to write a if statement in jQuery".
Such a combination is essentially needed merely to bring JavaScript up to a minimal level of usability. We generally don't find this to be the case with other, more sensible languages, which is why it seems so odd. C, C++, Java, C# and Python implementations come with a sensible language and a rich standard library. Developers using them don't need to bring their own standard library just to get a basic level of functionality.
You shouldn't make your trolling so obvious, man.
Note that jQuery is a pretty big (and complex) wrapper. Zepto provides a much smaller wrapper with a very similar (though not fully identical) interface. It used to be mobile-webkit-only but has since moved to "modern browsers".
I hear this point made a lot, for example in reference to learning Ruby before Rails or C before Ruby, but I don't think it's right. They used to teach kids Latin before Spanish or French (in the 1700s):
"We are told that it is proper to begin first with the Latin, and having acquir'd that, it will be more easy to attain those modern languages which are deriv'd from it" (quote from Ben Franklin's autobiography)
But that's silly and no one does this anymore because LATIN SUCKS and it's harder to learn Latin than any other language. jQuery is easier to learn than JavaScript. Why not start with jQuery and then learn JavaScript after?
On the other hand, it's quite a reasonable assumption that getting a good understanding of JavaScript gives a broader context of what is going on that is necessary to properly use jQuery.
Second, the argument that language X runs language Y under the hood so you should learn Y in order to get a good understanding of X doesn't hold. JavaScript is written in C++ in most cases, which compiles into assembly. So why not learn assembly to get a better understanding of JavaScript?
That's silly.
With all that said, I also lean towards "just learn what you want or need to know" train of thought. I think those of us who enjoy learning what's under the hood overestimate it's necessity for "getting things done". I don't think there's anything wrong with learning and using jQuery without diving into the messier details of vanilla Javascript unless necessary. Also, for many of us, those ugly situations when we are forced to figure out what's going on behind the scenes is when we actually understand it anyway.
After a certain amount of time, I got completely bored of making the computer count numbers with for loops and doing games using only "if", I wanted a GUI, something I could see. This proved to be insanely difficult (at that time)! So, somehow I came by PHP, suddenly I was doing things that I could see, god damn webpages, I was so happy, I was doing (not really) useful things.
I later noticed that some web page "did things without reloading", because, that was cool! So I came upon this thing called Javascript and, and read things about AJAX, it all seemed pretty cool, and I could make things work copying and pasting, but believe me, I had no idea what was going on! So suddenly, some strange thing with an awkward syntax came by called jQuery, and suddely I could do:
$('#myForm').ajaxForm(function() {
alert("Thank you for your comment!");
});
and everything worked exactly as expected, I loved this new "programming language". I later came to know that was not a programming language in itself, rather a library, and I swear that's when it freaking clicked, finally I understood what abstraction was, before I knew it I was doing all kind of more useful things, not only web now because I came upon python, another language that coincidentally abstract you from most of the common problems when coding.This story came out pretty long, but I the moral would be that the more abstract you are from the machine problems when you are starting the better.
Many argue that not knowing what goes on under the hood will make you a bad programmer, and I couldn't agree more! The problem is that you will have shitty programmers one way or another, I'm sure lot's of people who started by coding assembler never got to great programmers because they know where the bits are going.
Abstraction is probably the most useful weapon in our arsenal as human beings and we should make as much use of it as possible, get as far away as possible from the issues that don't concern the immediate problem you want to solve when you're starting. If that means starting with jQuery because you type less and thing magically work somehow, so be it.
If X is non-trivial and you need to support old/crappy browsers, then probably not (well, not without person-years of pain).
Conversely, if you can get away with targeting only IE9+, WebKit and Mozilla, or if X is dead simple, then almost certainly yes. And you should try it, too, because jQuery is a big warty kitchen-sink of a framework. In those cases these days I use CoffeeScript and a few simple homegrown helpers[1].
Faster maybe, but smaller probably not unless you rebuild half the jquery interface on top of straight DOM (and in that case, why not use zepto or some other similar library?)
Every time I try to go with straight DOM, it turns out to be a pain because the DOM interface as a swamp of javaisms unfit for human usage.
https://github.com/jawj/github-widget/blob/master/github-wid...
I have no idea what he's talking about. jQuery normalizes browser differences, but what on earth kinds of "errors" are "caught" by jQuery, that are "dangerous" to hide from the developer? I mean, I've used jQuery on projects for years, and I can't even imagine.
> document.getElementById("nonexistent").innerHTML = "";
This however will not cause any errors, it just won't do anything:
> $("#nonexistent").html("");
These sort of do-nothing-but-don't-throw-an-error responses can encourage developers to be less careful about making sure elements exist as they are expected, etc.
var a = [1,2,3,4]
// now i filter the array
var b = a.filter(function(a){return a<0} );
// b = []
// now do something on b
b.forEach(function(e){console.log(e)})
// will "fail" silently , because it will output nothing
is what i'm doing stupid ? yes, but it is 100% valid from a javascript perspective. It is a coding error , but not a JS error.Despite this, every time I start a new project that requires some DOM manipulation etc I lament at having to include the entire library just to harness a tiny aspect of it's power.
A delightful solution to this would be a similar degree of modularity as there is in, for example, jQueyr UI. I know there is a degree of modularity (https://github.com/jquery/jquery#modules-new-in-18) but this is reasonably high level and at this level the argument of using google's CDN and so encouraging a cache hit is still very strong. If you could strip both jQuery core and shizzle (I rarely/never use attribute selectors for example) right down to a hundred lines of so of what you really needed, this would be very very compelling.
I had a relatively brief investigation into the codebase a while ago with a view to how hard this would be to implement but didn't really have the time to follow it through. My conclusion was that it wouldn't be easy, anyone have any ideas/thoughts on this?
It was, and remains, great. But jQuery seems like an unstoppable force at this point.
https://github.com/jquery/jquery#modules-new-in-18
As far as I know the core team is planning to continue the trend along with a builder at some point. For my part I've proposed a separation of the dom manipulation from the collection and argument handling:
For that reason I and a friend started a project called Rye[1] that is a light wrapper around the DOM and other browser APIs; it's made of small modules that you can pick as needed. Despite being < 6kb, it also favours readability over code size, so it's easy to spy under the hood.
Ender[2], a hybrid library/package manager, has a similar philosophy.
[1] http://ryejs.com
Except that jQuery Core is a completely different thing. You know if you're using jQuery UI Menu but not jQuery UI Dialog so you can decide to include them or not with a custom web-based builder just by clicking boxes.
The jQuery Core features used by all the plugins you collected to build your site are not immediately obvious. Did they use .replaceWith() for example, is it safe to leave that out? What about .load(), did they use that API? Oh, wait, there are two different things that .load() does, one is AJAX-y and one is event-y, if they did use it which one did they mean?
By having the full library there you don't need to spend lots of time tracing down these dependencies. And in JavaScript these are all dynamic, you can never really be sure you got the dependencies right until you find out you didn't.
That's why I strongly advocate that the average programmer should just use the whole standard jQuery core library unless you are in some spot where saving 10-20KB gzipped is so important that you're willing to chase down those dependencies yourself.
Frankly with the amount of plugins I usually use (0-2) this isn't really problem...
The point is, there are some great features and fixes tucked away in there and sometimes I only want say <5-10% of the library, I could write it myself but then I loose all the collective knowledge embroiled throughout.
1. I found out I could use Rails helpers to make really cool stuff. It generated ugly JavaScript code and errors that no one could see. No one got hurt. Win.
2. I realized I could use Prototype.js directly. The code was still ugly, but I could do even more. I eventually switched to jQuery because of the large ecosystem.
3. I started buying and borrowing JavaScript books. I decided to use vanilla JavaScript. I realized that it was a pointless exercise because of browser incompatabilities: http://www.quirksmode.org/dom/w3c_core.html. Now I understand JavaScript, but use jQuery to interact with the DOM.
It's probably impractical to suggest people learn vanilla JavaScript first. People who find jQuery are going to use and love it. They are going to write ugly code, but they will actually be able to accomplish something. As time wears on, they will learn the finer points of the language.
In the end its just another case of knowing your tools and when to use 'em.
the goal of jQuery is not to provide a MVC framework , an AMD framework , or whatever that helps writing modular code. The goal of jQuery IS DOM manipulation and having a single API for every browser out here. And jQuery is a framework not a langage so your argument ( PHP==jQuery because it let's developers write ugly stuff) doesnt stand.
Those who think they are too smart to use it certainly are not real web-developers in real businesses , having to support legacy browsers because their client base still run on IE6. or they have enough time to work on all the quirks of IE6 IE7 IE8 each time they write a DOM related function , i dont...
jQuery is here for quick DOM manipulation, is basically a facade pattern, and the bright idea was to use CSS selectors to query the dom.
jQuery selector engine is far more powerfull than document.querySelector
Why is it hard to work with the DOM ? because it is STRONGLY and staticaly typed ! it has interfaces and type checking , so using it with a dynamic/weakly typed language is hard. the DOM doesnt use duck typing , that's why can get all these DOM ERROR , invalid DOM LEVEL call ,and you cant create an Element or a Node without a factory etc ... and let's give credit to MS on this, they created DHTML because they understood it made little sense using that api with that language ( each time you are using innerHTML it is DHTML, querySelector to until it was made a standard ).
yet I dont see people saying they are too smart to use DHTML because it is not pure DOM. but do they really care about what interface is used ? how the factory method build the given objects ? i dont think so.
It exists for a second reason as well: make DOM interaction not suck. Because they suck hard out of the box.
> Why is it hard to work with the DOM ? because it is STRONGLY and staticaly typed !
Not really. It's because it's defined through a very restrictive abstract language which assumes almost nothing about the implementation language (basically, that the implementation language has method calls and a name can map to multiple arities somehow). That gives an API which can be implemented on pretty much any object-oriented language, but will also suck on pretty much all of then.
> querySelector to until it was made a standard
Uh... no it was not, if you want to give MS credit where credit is due you can give them XMLHttpRequest, but definitely not querySelector which is a WhatWG brainchild (the first revisions were by Anne van Kesteren and Lachlan Hunt). MSIE didn't get querySelector until IE8 (March 2009), Webkit landed it in December 2007 and Gecko in July 2008.
Also, innerHTML was standardized as part of the HTML5 effort, as well as a number of ther "DHTML" features.
And while you give praise to MS, don't forget to criticize them for e.g. not having implemented the DOM Events API until IE9.