Bling – the $ of jQuery without the jQuery
gist.github.com
gist.github.com
jQuery was a game changer for web client side development. Thousands of work hours have been spent on it. It had a specially important role of dealing with all the inconsistencies between browsers. If you don't use all the features, nowadays you can just create a custom build with the stuff you want.
If you don't need jQuery, maybe because you only care about modern browsers, or you use another library or you don't mind a bit of extra boilerplate for DOM manipulation, that's perfectly fine. But these kind of posts seem like mockery on the developers of a library that has provided extreme value for thousands for developers over many years.
The primary problem is that the zepto.Z function overrides dom.__proto__, which prevents many JIT optimizations. Overriding an object's __proto__ property is strongly discouraged and will be deprecated in ES6 --Firefox bug 947048
But honestly, if you load jQuery from a big-time CDN, chances are your users already have it cached and don't need to load anything.
Furthermore, I don't think he's making up a strawman at all now matter how you look at it. He agreed with the article. You CAN re-implement jQuery in 10 lines of code if all you want is 0.1% the functionality of jQuery. That's what the article said and it is true. It's not an argument against any perceived strawman.
The next paragraph was praise for jQuery and the final paragraph said it's fine to not use jQuery and added an opinion about what "these kinds of posts seem like". Where's the strawman?
Headlines are supposed to be ambiguous, in the sense that they are much shorter than the content they accompany (and thus there are fewer possible headlines than there are possible articles). You're expected to read the content.
Whenever I've decided I know best and used Zepto or something else it introduces weird bugs and then someone decides we need to support IE8 because their Dad still uses it...
If behaviour is considered irrelevant, here's my one-line implementation of $:
var $;1. Its the DOM selection function. This is what he's replacing. This is the real "functionality" of the $ function. The main bit missing is that it won't create a new element if you pass in a string.
Return a collection of matched elements either found in the DOM based on passed argument(s) or created by passing an HTML string.
2. Its a Namespace for all the rest of Jquery. This is NOT what Paul's replacing but is kind of ancillary and really just good housekeeping for a js lib.
$(function(){console.log('DOMContentLoaded')})
Yes, that's precisely the author's point, except that you might not even need to make custom jQuery builds. You might be able to just use these few lines.
> But these kind of posts seem like mockery on the developers of a library that has provided extreme value for thousands for developers over many years.
There is absolutely no implication of mockery, and anyone who knows anything about Paul Irish knows how laughable that accusation is.
We will always need jQuery. We need a well maintained library that addresses browser inconsistencies and provides a better API. (Don't expect my gist to be maintained like jQuery is. :) I wrote a doc a year ago documenting all the bugs jQuery fixes for you (linked elsewhere in this thread). The jQuery team is talented and I respect their dedication and work greatly. I'm also interested in a conversation about what developers want most from their browser JS stdlib. Because whatever a developer's answer is, shouldn't they be able to get a custom build of that?
jQuery has, for better or worse, become such an integral part of web development, the $ namespace is pretty much owned by it at this point.
If you do want to use it for not-jquery, it should be something that is drastically different so someone new trying to patch a bug on prod doesn't run around in circles wondering why their code that should be working is not.
The bling.js project by repurposing $ into something that looks like it might be jquery but isn't, is just a bad idea.
I wonder, why that is not done more, after all it is one of the benefits of prototype based inheritance, that you do not have to subclass to change the interface.
Of course, the horse is out of the barn on the personal $ library front, so maybe Irish doesn't have to worry about inadvertently influencing people badly. There already was a no-library/micro-library trend 4-5 years ago where lots of people would write their own tiny jQuery-like DOM utilities, and I've worked on a few projects where someone used jQuery-like idioms for their partial reimplementation (I call them "nayQuery"). Even the better ones are a pain where they subvert expectations. And of course, when someone later decides to add jQuery to the project (makes sense, jQuery does more and has an ecosystem around it), now you're using $ for the custom library and jQuery for jQuery, which is disorienting.
I've written my own version of what Irish presents here -- it's a useful exercise, I appreciate his contribution (helps me think about some different ways to approach it), and sometimes it's even concretely useful when you're getting started on a small project with a limited browser target where the rest of the codebase is going to be smaller than jQuery itself.
But when I write something like this, I always name it differently than $.
1. Alias document.querySelectorAll to $. 2. Alias node.on to node.addEventListener. 3. Make NodeList a sub-type of Array (so you can use forEach etc on node lists as you would on arrays).
The $ of jQuery also does a few other things, e.g. create HTML elements from text ($('<div class="foo"/>') creates a div element with CSS class "foo") and wrap elements in a node list ($(document.body) creates a node list containing document.body).
[0]: https://gist.github.com/MadeByMike/7e7707eff116229a5948
This is not correct. You may say that it wraps or outputs elements in a node list like object but it is not the real deal. If you examine the emitted jQuery objects using instanceof or any other method, you'd see that they are not related to NodeList in any way. They're just generic objects of Object type.
Those reasons being:
* because it's garbage
* because native objects shouldn't (and may not necessarily be) extended
* because static nodelists didn't even exist back when jquery was created
* because you can't create a nodelist in userland code
* because NodeList instances are host objects and host objects often behaved in unexpected ways in older browsers and IE
If you want to have a look at host object weirdness, try using `console.log` as if it were a function when using the F12 developer tools in IE8. Surprise: it can be invoked like a function, but it doesn't have any of the methods you'd expect a function to have (e.g. apply, call, let alone bind). Another host object quirk was that they were often read-only (which is why "thin" AJAX libraries can't manipulate the native XHR objects directly if they want to support IE8).
"Who cares about IE8?" you ask? Surprisingly some sectors of certain industries still do (civil service in Germany, for example). If your market overlaps with those groups, you'll be thankful most of us were at least able to skip IE7 after IE6 finally died (I'm not sure whether we'll be as lucky with IE9 when IE8 finally bites the dust).
Bull. Shit.
This document proves why, and is written by the same guy that is now pushing this “you don’t want jQuery!” stuff.
https://docs.google.com/document/d/1LPaPA30bLUB_publLIMF0Rlh...
You don't "need" jQuery, but you might not-not need jQuery unless you do something about those bugs.
yell.com mobile site removed jQuery from their codebase, and used that list during the process. Looking at each bug, does it affect them, yes/no. If yes, code around it.
I'm a jQuery fan, but sometimes you might not need jQuery, but sometimes you might not-not need jQuery
> Bull. Shit.
Depends on the target environment(s). If you only want to support evergreen browsers then there is no reason you need jQuery; you're going to have the native DOM APIs and you don't care about compatability.
jQuery's big win is two fold, in my opinion. One it has awesome, chain-able syntax and two (most important) it has awesome backwards compatibility with terrible browsers. If you don't need two then is one worth bringing in another dependency? Maybe or maybe not.
False.
Read the first sentence of the document I linked to.
“…developers should be aware that ditching libraries, like jQuery, can easily require large amounts of research on their end to avoid bugs (even in modern browsers).”
Bear in mind it’s Paul Irish who wrote that.
> Read the first sentence of the document I linked to.
Oh I did. Look through many of the bugs they outline; many are incredibly minor and inconsequential unless you're doing things related (or semi related) to supporting older browsers.
> Bear in mind it’s Paul Irish who wrote that.
Yup; I don't see his posts being quite in conflict like many here seem to think. Plus his opinion has probably evolved overtime anyway (he wrote that document a year and a half ago).
function $(q) { return document.querySelector(q) } function $(q, parent) { return (parent || document).querySelector(q); } function $(q, parent) {
parent = parent || document;
return [].slice.call(parent.querySelectorAll(q));
} Array.from(<NodeList or other iterable>)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... $ = document.querySelector.bind(document);
would be sufficient? ;)with experimental ES7 syntax :D https://github.com/zenparsing/es-function-bind
Though I think most the people moving away from jQuery are doing it because the browsers have become more consistent in how they run JS.
I think that's a good thing.
jQuery as a library has now become huge, and a lot of projects probably don't use the full feature set. With modern browser support converging and older browsers being edged out of the usage stats, there's not as much need for the cross-browser portions of the library anymore. Enough so that newer versions of jQuery have dropped support for those browsers as well.
So if you can cut down your cold cache loading times by not including the full jQuery library, that's probably a win (especially on mobile). You can do this by using a custom build of jQuery, but I guess some developers are taking this opportunity to go "back to their roots" and see how Javascript has changed since jQuery became a de-facto include in every project.
I think there's a lot more maturity in the language these days, and by using native JS methods there's probably opportunities there for browser optimisations that aren't available using helper methods written in JS that accomplish the same functional goals.
But I'm not a browser devevloper or a JavaScript expert, just a long time web developer who remembers the times before jQuery was in every project. If it's a crutch, it's one I will remember fondly.
> jQuery as a library has now become huge
> So if you can cut down your cold cache loading times by not
> including the full jQuery library, that's probably a win
jQuery 1.11.3 is 38.4 KB when minified and gzipped.jQuery 2.1.4 is 34.1 KB when minified and gzipped.
I'm all for eliminating unnecessary bloat, but it's not as if a jQuery download is a huge amount of data to fetch. While jQuery is not a framework, most front-end JS frameworks are the same size or bigger and don't receive as much attention for being bloated.
If you can get by without jQuery, or if you have a very large number of mobile users and first-load performance is mission-critical for your application, or if you have a large percentage of users from countries with slow or intermittent internet connections, then sure, avoiding jQuery makes sense as a priority. But for most applications, jQuery is a smaller download than a single medium-resolution highly optimized image, and it can be cached forever.
Your comparison with "a single medium-resolution highly optimized image" doesn't hold for mobile phones. On mobile phones users expect latency when loading images, but not when loading the UI. Another problem is that JQuery is not the only commonly used library. You add Underscore, you add Angular, or whatever libraries du-jour we have and pretty soon we are talking about 100 Kb of stuff or even more that is rarely used as a whole.
Of course, my use-case is about having really simple interfaces augmented by Javascript and meant for mobile phones. Well, for complex interfaces I think bringing in JQuery as a dependency may be worth it, but then again, I then start thinking that JQuery is not enough. It's because I want more, I want a virtual DOM that's saner by design, I want to work with immutability, I want much better performance without unpredictable behavior (like what you get with Angular) and I want to only pay for the features I use. JQuery is incompatible with React and is incompatible with Google Closure in advanced mode.
I also agree that jQuery isn't the end of what gets added... once you add a few additional libraries it gets very big, very quickly... I'm working on a project now that is loading about 19 jQuery plugins in addition to jQuery, as well as a handful of both bootstrap and jQuery-UI extensions, and the payload of a relatively simple page is coming in over 2MB (even if most of that caches, it's really big for a first hit).
People tend to start with a kitchen sink, then add not only the rest of the kitchen, but the barn as well without a thought or consideration to the final result, and the payload that goes with it.
However, let's be clear here: most people who complain about the size of jQuery are doing so without any basis whatsoever. And even if people are measuring, they may not be measuring the right things. If not using jQuery causes you to reduce your Ajax usage, and reload entire pages as a result instead of only reloading the content, the end result is a slower site.
Remember size isn't as much of an issue when it's less than 100kb (though 3G or less networks that will still be painful). The biggest issue is yet another file for the browser to fetch. Synchronously or asynchronously the browser will still open another connection to the server to grab the file which results in further latency before your application really starts up.
There's no reason you can't concatenate jQuery with the rest of your JS.
True and most applications should really do this. In reality I've seen far too many production system still including sometimes over 50+ files.
Less javascript means less cycles burned executing boilerplate framework factories means faster page loading means longer battery life means you can keep that two year old phone that's not quite so fast instead of throwing it in the trash.
jQuery causes global warming. (tongue-in-cheek of course, but not entirely)
As much as I'd love to stop keeping track of IE8 bugs, for a lot of sites this isn't possible. And, IMHO, this cavalier attitude is what causes many websites now to work "best" (read: only) in Chrome. It's true that a lot of sites (I'm thinking Webapps) don't need jQuery at all, and a lot of sites can get away with just using Sizzle, but 28kB is a small price to pay for the utility functions, cleaner AJAX API, event binding registry, etc. If you don't need them, by all means don't use it.
In 2015 most browsers are in much better shape than they were in, say, 2007. A lot of people are mostly targeting users who use up-to-date, standards compliant browsers. They are also often targeting people who use mobiles, which are (for a couple of reasons) much more sensitive to poor JS performance than desktops, and also see a more tangible benefit from small page sizes.
Another advantage to jQuery was making complex JS operations very simple. Modern JavaScript has actually made life much easier[1], meaning that it's often only a little more work to use vanilla Javascript.
On one hand it may be a nice way to show to people that what they use in jQuery can be written in a few lines of pure JS.
On the other hand it encourages people who could use pure JS (because they only use a small portion of jQuery) to stick with some non-standard helper syntax.
Or in other words - replacing an ugly, verbose API with a widely recognised alternate syntax!
Right. 35 characters.
> "…but jQuery API is no better"
Your jQuery example is 11 characters.
I can’t believe you’re using verbosity as a measurement, while at the same time claiming 35 and 11 are the same.
Does. Not. Compute.
The problem is that "jQuery" function, aliased as "$" has 9 signatures (doing 9 different things, depending on which arguments you send to it), while querySelectorAll does only one thing
That said, test the 2 approaches and see which works better for your site.
When do you need to do that?
[].slice.call(document.querySelectorAll(...)).forEach(function () {})
Because a lot of array methods are "generic", i.e. operate on array-like objects instead of just arrays, that can be "compacted" to [].forEach.call(document.querySelectorAll(...), function () {})
but neither are very nice. [].slice.call(document.querySelectorAll('.foo')).forEach(...
It "casts" the NodeList which is "Array-like" to a proper Array, which has forEach, map and other useful methods in its prototype.Then aliases `$` as a selector function.
So it uses "doc" instead of "$" but feel free to fork :-)
https://gist.github.com/vectorsize/feda8ac1ebc889c33b6f
not as tested as yours…
This will make our lives easier :)
I wish that someone would write a drop-in javascript replacement for jquery in the context of bootstrap.
.text: $('.selector')[0].textContent
.css $('.selector')[0].style
.html: $('.selector')[0].innerHTML
.val: $('.selector')[0].value
.first: $('.selector')[0]
.closest: n/aI can use key-value object to assign multiple css property, and it can set the style on all matched nodes.
If there are no matched elements, Bling's $()[0].xxx = value" will raise exception.
$('.foo').forEach(el => el.textContent = 'bar')
$('.foo').forEach(el => el.style.top = '0px')Yep, this submission is Hipster 1.0 Certified.
2) Semicolons are still in debate amongst the JS community, I don't think there's a consensus on whether they're needed or not and it seems to boil down to personal preferences.
3) This reeks of ad hominem, how exactly is Paul Irish "hipster"? Strikes me as someone who's done a lot of work to make the web a better place for all of us, fine with me.
They are needed.
This
var func = function(x) { console.log(x); };
func;
(42);
is different from this var func = function(x) { console.log(x); }
func
(42)Knowledge about how ASI works, on the other hand, is mandatory.
Which becomes really annoying if you just want to quickly concatenate a few files together.
Sure, it's something that you can fix yourself; I'd consider it a common courtesy to include at least one, though.
[file1, file2, file3].join(';\n')
albeit if you're using any kind of post-processing tool, like UglifyJS or Google's Closure compiler, then everything just works, as these tools actually parse JavaScript. There's usually no need to explicitly concatenate the code prior to minification or other processing.So they're not really optional. What they are is necessary and if omitted the engine attempts to put them in automatically. The rules for automatic semicolon insertion are in section 7.9 of the ECMAScript 5 standard (http://www.ecma-international.org/publications/files/ECMA-ST...).
This means you're omitting something that is required by the engine but not necessarily required in the syntax which boils down to you losing control of where semicolons end up possibly making your code do something you did not intend because you either misunderstood the rules of automatic semicolon insertion or there was a bug in the syntax parser being used.
Bad programmers that can't understand ASI will be also confused by the floating point semantics, promises and other basic concepts — there are many ways of "making your code do something you did not intend" in JS, but that's no excuse for bashing language features.
Fact check: ASI is a fully legitimate part of the language (as in, it's in standard, it's documented, and supported across the board), so demonizing it is every bit as silly as e.g. deprecating C macros.
Learning the language helps with the the issues you outlined, while magical thinking (uguuu, semicolons good, no semicolons bad, uguuu) for the most part doesn't.
This is a terrible attitude. There is no reason you may not understand every case in which a semi colon is automatically inserted but can still understand floating point, promises and other things. Automatic semicolon insertion isn't really a "basic concept"; it's a convenience for those who elide them and nothing more (the ECMAScript 5 standard even states this).
> Fact check: ASI is a fully legitimate part of the language (as in, it's in standard, it's documented, and supported across the board), so demonizing it is every bit as silly as e.g. deprecating C macros.
I'm not "demonizing" it but if you look at the standard the engine still requires semicolons it just fills them in for you if you miss them. This is vastly different than your deprecation of C macros example. Yes it's documented but it's non-obvious unless you've literally looked it up to learn it. I'm also not sure why you insisted on letting me know it's a "fully legitimate part of the language (as in, it's in standard, it's documented, and supported across the board" when I linked to the standard and stated exactly where to look for its definition...
> Learning the language helps with the the issues you outlined, while magical thinking (uguuu, semicolons good, no semicolons bad, uguuu) for the most part doesn't.
Sigh. Automatic semicolon insertion is only documented. There are no errors or warnings or other information. Many developers, who understand more advanced topics, may not even know about it. The language does nothing to help with this. It's far better to be more explicit than assuming everyone who looks at your code understands the full ECMAScript 5 standard.
Javascript never should've had C-like syntax if it was to have the feature set it does. Its syntax descends from a tradition of languages that have none of its actual features. Most other C-like languages have block scope[0]. So the syntax PLUS the terrible, awful, no-good very bad name lead you to believe it's more-or-less dynamic Java, when nothing could be further from the truth.
[0] ...and require declaration before usage, and have sensible 'this' semantics, and are class-based, and have function parameters that are more than just syntactic sugar, and have ACTUAL arrays, and...
console.log("woof")
(function() { console.log("foo") })()
Without semi-colons, that blows up (with a super unhelpful error message, to boot). Sure, if you understand ASI in JS, then you'll figure out the problem very quickly. But if you just always use semi-colons, then ASI is one fewer thing to have to worry about. console.log("woof")
void function() { console.log("foo") }()
There really is only one ASI rule you need to remember [0] in practice: don't begin a new line with ( or [ if it's intended to be a new statement.On this topic, it could so easily have been different; I found this interesting from Brendan Eich [1]:
> I wish I had made newlines more significant in JS back in those ten days in May, 1995. Then instead of ASI, we would be cursing the need to use infix operators at the ends of continued lines, or perhaps or brute-force parentheses, to force continuation onto a successive line. But that ship sailed almost 17 years ago.
> ...My two cents: be careful not to use ASI as if it gave JS significant newlines...
[0] this is technically a lie because everybody needs learn the other one whether they use semicolons or not: don't put a linebreak after the "return" keyword :) [1] https://brendaneich.com/2012/04/the-infernal-semicolon/
Here's an even easier and clearer one: finish every statement with a semicolon.
function hello() {
var x = 0;
return
{
x: x,
y: y
};
};
Just putting semicolons where you think it can work won't help you. If you write javascript, you must know what the asi does. So semicolons or no semicolons is completely irrelevant.Personally, if all is encapsulated inside self executing function, i put one semicolon before and one after it.
function v(x) {
return
x;
}
v("yeah");
returns undefinedNewline matters / doesn't matter, the same with the semicolons.
> not sure exactly how he's "wrecking jQuery"
The grandparent is misguided, but I believe they mean using '$' as the QSA. The grandparent probably uses script tags and globals in which case there would be a conflict if a script tag library requires window.$.
JS modules should var $ = require('jquery') (or equivalent) and then use the $ in their local scope if they need jquery.
(function(window,$){
//module code goes here
}(this.self || this, jQuery));
In this way, you are keeping jQuery itself and your implicit scope assigned to localized variables.If you are writing a modern module (not necessarily jQuery based), then following node/cjs conventions is probably best. If you use this convention with such a plugin, said module should probably return the jQuery object that has been modified, and extra care should be taken that all plugins are using compatible/same instance of jQuery.
[1] https://github.com/feross/standard [2] https://github.com/Flet/semistandard
This is definitely progress. I’m quite convinced that the users of our applications will feel the difference, and they’ll love us for it.
Wow.