Anyway, jQuery always did the job, use it forever if it solves your problems.
Anyway, jQuery always did the job, use it forever if it solves your problems.
which I found while doing some performance work at one point. intercooler.js started as a custom function that hooked .load() in based on custom attributes (a trick I learned from angular 1.x)
deeply respect and love jquery
While presumably jquery is slower than native selectors, maybe that could be pre-computed away.
If the verbosity bothers you, you can always define an utility function with a short name (although I'm not personally a fan of this kind of things).
https://developer.mozilla.org/docs/Web/API/Document/querySel...
https://developer.mozilla.org/docs/Web/API/Document/querySel...
https://developer.mozilla.org/docs/Web/API/Element/querySele...
https://developer.mozilla.org/docs/Web/API/Element/querySele...
But you might still break stuff in your own projects. Imagine you extend a native prototype with a method, and later the native prototype starts having a method with the same name.
Newer libraries start using that new standard method.
You upgrade the libraries your website depends on, or add a dependency, and this new code happens to depend on that native prototype. Only you replaced it with your custom method, and that method likely doesn't have the exact same behavior. You broke that new code and fixing this might not be trivial because uses of your custom method are sprinkled everywhere in your code.
It only works if you ever works on projects that have zero dependencies, or dependencies you never update.
Or you could spare yourself the troubles and define a method that takes the node in parameter.
It's also a question of forming good habits: you could be working on your projects now, forming a habit of extending prototypes, but will you remember not to do this the day you write a library?
By the way, how can you be sure you won't move some of your app code to a library because you like your utility functions and would like to reuse them in another project of yours? And why not open source that shared code, so you can just install it with NPM? Bam, that stuff is a library now.
He was suggesting adding a prototype method, not replacing one. Unless the library your using is also adding prototypes, I can't think of an issue with this. Sure, if a new version of JS ends up using these names then things could break, but I'd bet this won't cause him a problem in actuality.
For anyone that didn't know, IE8 implemented native JSON.(parse/stringify) methods, and the second parameter is a hydrator/dehydrator... however, if you added custom properties/methods to Array or Object prototypes, they would throw an error you couldn't catch in JS... so to work around, you'd have to load the JSON library and use it under a different name, in ALL your code, because the native implementation was locked/sealed and couldn't be masked out.
Second most annoying IE bug was 5.0.0 and the old/new api's for dealing with select elements. New worked, old broken, have fun.
const $$ = document.querySelectorAll.bind(document);
(function (global) {
function $(selector, context = document) {
let elements = [];
if (typeof selector === "string") {
elements = Array.from(context.querySelectorAll(selector));
} else if (selector instanceof Element || selector === window || selector === document) {
elements = [selector];
} else if (selector instanceof NodeList || Array.isArray(selector)) {
elements = Array.from(selector);
} else if (typeof selector === "function") {
// DOM ready
if (document.readyState !== "loading") {
selector();
} else {
document.addEventListener("DOMContentLoaded", selector);
}
return;
}
return new Dollar(elements);
}
class Dollar {
constructor(elements) {
this.elements = elements;
}
// Iterate
each(callback) {
this.elements.forEach((el, i) => callback.call(el, el, i));
return this;
}
// Events
on(event, handler, options) {
return this.each(el => el.addEventListener(event, handler, options));
}
off(event, handler, options) {
return this.each(el => el.removeEventListener(event, handler, options));
}
// Classes
addClass(className) {
return this.each(el => el.classList.add(...className.split(" ")));
}
removeClass(className) {
return this.each(el => el.classList.remove(...className.split(" ")));
}
toggleClass(className) {
return this.each(el => el.classList.toggle(className));
}
hasClass(className) {
return this.elements[0]?.classList.contains(className) ?? false;
}
// Attributes
attr(name, value) {
if (value === undefined) {
return this.elements[0]?.getAttribute(name);
}
return this.each(el => el.setAttribute(name, value));
}
removeAttr(name) {
return this.each(el => el.removeAttribute(name));
}
// Content
html(value) {
if (value === undefined) {
return this.elements[0]?.innerHTML;
}
return this.each(el => (el.innerHTML = value));
}
text(value) {
if (value === undefined) {
return this.elements[0]?.textContent;
}
return this.each(el => (el.textContent = value));
}
// DOM manipulation
append(content) {
return this.each(el => {
if (content instanceof Element) {
el.appendChild(content.cloneNode(true));
} else {
el.insertAdjacentHTML("beforeend", content);
}
});
}
remove() {
return this.each(el => el.remove());
}
// Utilities
get(index = 0) {
return this.elements[index];
}
first() {
return new Dollar(this.elements.slice(0, 1));
}
last() {
return new Dollar(this.elements.slice(-1));
}
}
global.$ = $;
})(window); const $ = (s, e = document) => e.querySelector(s)
and a similar one for $$.I do agree with the notion that jQuery is easy to mishandle when logic grows beyond a pretty narrow (mostly stateless) scope. It’s fantastic up until that point, and incredibly easy to footgun beyond it.
FWIW, also hated the old ASP.Net Webforms round trips (and omg massive event state on anything resembling dialup or less than a few mbps in the early 00's).
I just wish that React and other SPA devs kept some awareness of total payload sizes... I'm more tolerant than most, but you start crossing over/into MB of compressed JS, it's too much. Then that starts getting janky.