Vanilla JS, fast, lightweight, cross-platform framework(vanilla-js.com) Vanilla JS is a fast, lightweight, cross-platform framework
for building incredible, powerful JavaScript applications. |
Vanilla JS, fast, lightweight, cross-platform framework(vanilla-js.com) Vanilla JS is a fast, lightweight, cross-platform framework
for building incredible, powerful JavaScript applications. |
That cross platform bit is the weakest link sigh.
Of course, most developers still have to target older browsers, but for a private Web app where you know your target audience, this shouldn't be a huge issue.
$('p').text('Hello.')
over for (var p in document.getElementsByTagName('p')) { p.innerHTML = 'Hello.'; }
any day!If you really think more people should be using plain vanilla JavaScript (and in a lot of places, I think this is actually true and even when a framework is needed, it's good to have the underlying skill) then the way to get them to do that is to educate them on it, not patronize.
Aside from not being cross-platform, VanillaJS is just plain ugly.
We finished the exercise assuming the example used jQuery instead.
Did you expect your interviewees to have memorized APIs? There's Google so that you can look up those when needed.
There always is either underscore or backbone or require or dojo or prototype or yui or jquery...
Don't really know if this is good or bad!
Not really. Just replacing document.getElementsByTagName by document.querySelectorAll (the native, browser-implemented version of what jQuery does) will generate a 150-200x perf hit depending on the browser.
The reason for that is twofold: first, getElementsByTagName doesn't have to parse the selector, figure out what is asked for, and potentially fall back on explicit JS implementation (jQuery supports non-native selectors. In fact, I believe you can implement your own selectors). But the parsing overhead should be minor in this precise case.
Second, the real reason for the difference, getElementsByTagName cheats something fierce: it doesn't return an Array like everybody else, it returns a NodeList. And the nodelist is lazy, it won't do anything before it needs to. Essentially, just calling document.getElementsByTagName is the same as calling an empty function. If you serialize the nodelist to an array (using Array.prototype.slice.call), bam 150~200x perf hit.
See http://jsperf.com/vanillajs-by-tag/2 for these two alterations added to the original "vanilla JS" perf cases.
There is a significant overhead to jQuery, but it's ~3x compared to the equivalent DOM behavior, not 400x.
Depends what you mean by "for real". The document.getElementsByTagName comparison is bullshit: gEBTN is lazy, just calling it basically doesn't do any work, it just allocates a NodeList object and returns.
If you serialize the nodelist to an array or use document.querySelector instead (it returns an array) you get ~3x between the native version and the slowest libraries, not 400x.
What gets me is when people include jQuery and then further bog things down by loading a lot of plug-ins to do things that could easily be accomplished by adding a few lines of code of their own. Even if you do need and include jQuery, it doesn't mean you have to use it for every piece of javascript in your app.
Many times, a plug-in will do a lot more than you need it to do. If your primary goal is to just get rid of the 300sm delay translating tap events to click events, you don't need a library for full gesture support. You need half a dozen lines to listen for touch events.
If you just need to add some client-side persistence for a few basic things in LocalStorage, you probably don't need a plug-in with a complex query syntax.
Cannibalize a library if you need to and pull out the bits you need. You don't have to include the whole kitchen sink.
That's what Zepto[0] is for: jQuery's API, 20% of the size (although it drops some features, e.g. $(selector) is pretty directly proxied to document.querySelectorAll, so $('> .foo') works in jQuery but blows up in Zepto)
can be written as
jQuery.post('path/to/api',{banana:yellow},function(data){alert("Success: "+data);});
much simpler and easy than
var r = new XMLHttpRequest(); r.open("POST", "path/to/api", true); r.onreadystatechange = function () { if (r.readyState != 4 || r.status != 200) return; alert("Success: " + r.responseText); }; r.send("banana=yellow");
nevermind got the joke. but i think jQuery helps write faster code sometimes
Heh.
jQuery has to parse the selector and figure out that it's of the form "#id". This requires running a regular expression. A lot more is happening.
The whole jQuery call from start to finish takes 2.85 microseconds, in what is presumably a real benchmark, but microbenchmarks like this are hard to interpret and basically meaningless. But yes, if your app needs to do a burst of 350,000 jQuery calls in a tight loop and you are bummed that the whole thing takes a full second, you should then optimize using document.getElementById.
The sentiment is borne out by the facts when you dig a little deeper. Just calling document.getElementById without using the return value does not actually dig into the DOM and find the element according to this comment: http://news.ycombinator.com/item?id=4436438
Seems like you might have some other optimization work to do at that point :)
Either way, long-term caching of such shims means the bandwidth to load polyfills only has to be expended once per client. And an extra Mb of bandwidth once per year is a pretty reasonable thing to do for particularly older browsers if it makes your development more sane.
Some JS people (the ones usually with a long beard) hate how kids use frameworks like jQuery and this site is an attempt at telling them "The vanilla JS, i.e. the standard language that all browsers use and your cool jQuery leverage under the hood, is quite capable these days. Use it". They are not quite right, but aren't quite wrong either (IMO). You'll be a dreadful JS programmer if you only know jQuery. JS is sooo different from C (and Java) that if you don't know the core language everything you'll do will be wrong. For starter: there's no block scope. Only function scope.
Every JS programmer should read "JavaScript: The Good Parts" by Douglas Crockford cover to cover - before learning jQuery.
There is global scope as well, and it's (unfortunately in most cases) the default.
(Speaking as a medium-sized corporation user stuck on Snow Leopard. :] )
I'm just happy its happening at all, I know people at banks that have IE6 still.
http://gs.statcounter.com/#browser_version-ww-daily-20120820...
The proper way is:
for( var i=0, ps=document.getElementsByTagName('p'), len=ps.length; i < len; i++) {ps[i].innerHTML = 'Hello.';}
Edit: I think I missed what you said. You're saying it's "like" and array, but unlike arrays its `length` is enumerable. I'll leave my comment so other skeptics can benefit :)
Edit2: This is what I was referring to (read the 'Note' at the right side): http://bonsaiden.github.com/JavaScript-Garden/#object.forinl...
paras = document.getElementsByTagName('p') for (var para in paras) { console.log(para)} 0 1 ... 9 10 length item
var paragraphs = document.getElementsByTagName('p');
paragraphs.forEach(function(paragraph){paragraph.innerHTML = 'Hello.';})
document.getElementsByTagName returns a DOM Node List and it does not have forEach method according to the DOM spec. DOm Nodes, Elements and Node Lists and Node Maps do not follow the javascript spec (ECMAScript) hence do not share methdos and properties. A Dom Node List does not have the methods of the javascript array. That is because DOM Node List does not inherit from the Array.prototype, because it is not javascript - it has its own spec that exactly determines what methods and properties it should have. The implementation in the browser happens to be accessible through javascript but that does not mean that the DOM is part of javascript. That is why wrapper libraries like jQuery or other abstractions are necessary to make the DOM much more accessible from a JS perspective. BTW that is why many people confuse DOM with javascript and then get frustrated which is understandable.
for (var p in document.getElementsByTagName('p')) {console.log(p);}
This discussion is a bit like how assembly programmers used to defend not moving to a high level language long after the performance benefits were not worth it any more.
Such as?
Yes, but it's also more probable that it won't go on at all (due to browser incompatibilities and such).
ps. second example is not valid, in Vanilla JS you do it like this:
document.getElementsByTagName('p').filter(function(el) {
el.innerHTML = 'Hello.';
});Array.prototype.forEach.call(document.getElementsByTagName('p'), function(el) { el.innerHTML = 'Hello.'; });
TypeError: document.getElementsByTagName("p").filter is not a function
Because you don't get an array, only something array-like.
Erm... no you don't: http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-F68F082
but never mind:
Array.forEach.call(paragraphs, function(paragraph){paragraph.innerHTML = 'Hello.';})
will work fine.
$ isn't just a syntax layer on top of querySelectorAll. When you do $('p'), it first queries the DOM for everything that matches that selector, then it creates new jQuery objects to wrap each of the returned nodes as well as creating a jQuery object to contain them.
If all you're doing is setting the innerHTML of these objects, it's a non-trivial overhead.
[1] https://github.com/jquery/jquery/blob/master/src/manipulatio...
But we're not at that point in the web yet. The performance benefits are worth it. Just try out JQuery Mobile if you want to see what wasted CPU cycles can do.
The point is we're well past the point where grasping for the asm-equivalent from the start should be the default unless you happen to specifically target one of those niches.
That's still going to be a lot of work if the performance issues turn out to be many separate jQuery calls spread all over your code, which is not unlikely.