Replacing jQuery with native Javascript in our projects
jQuery was released at 2006. It was initially created to fill gaps between browsers. Today – ten years later – things are quite different. There are no such differences anymore and Javascript is more standardised. So it’s fair to ask if jQuery is needed anymore? It adds a dependency but does it provide enough value? I think we are just used to automatically add it and we never really think if it’s worth of it.
So I decided to do a small exercise. I took eight of our last projects and searched for jQuery usage with this bash snippet:
find . -path "*assets*.js" | xargs grep -h \$[\(\.]
Then I took most used jQuery commands and searched for native alternatives. This it what I found:
Probably the most common use of jQuery is querying DOM:$('.element')
There is a direct native equivalent to this:document.querySelectorAll('.element')
So what about looping through elements?$('.element').each(function(el) {})
This is little bit trickier since querySelectorAll returns a NodeList, not array. That’s why forEach and for…in loops are unsafe. So far it seems that good old for-loop works the best:var elements = document.querySelectorAll('.element');
for (var i = 0; i < elements.length; i++) {}
Adding a click event listener:$('.element').click(function(e) {})
JavaScript equivalent:document.querySelector('.element').addEventListener('click', function(e) {})
Traversing DOM:$('.element').parent()
$('.element').next()
$('.element').previous()
Native DOM alternatives:document.querySelector('.element').parentNode
document.querySelector('.element').nextElementSibling
document.querySelector('.element').previousElementSibling
Modifying attributes:$('.element').attr('href', 'https://www.evermade.fi')
Plain JavaScript:document.querySelector('.element').setAttribute('href', 'https://www.evermade.fi');
Modifying data attributes works similarly. In jQuery:$('.element').data('title', 'Cats & dogs')
And in pure JavaScript:document.querySelector('.element').setAttribute('data-title', 'Cats & dogs')
And there is also a dataset attribute available:document.querySelector('.element').dataset.title = 'Cats & dogs'
Manipulating classes:$('.element').addClass('red')
$('.element').removeClass('red')
$('.element').toggleClass('red')
DOM elements has classList property that can be used to manipulate classes:document.querySelector('.element').classList.add('red')
document.querySelector('.element').classList.remove('red')
document.querySelector('.element').classList.toggle('red')
Manipulating styles directly:$('.element').css('font-size', '1rem')
And without jQuery:document.querySelector('.element').style.fontSize = '1rem'
inArray helper:$.inArray('dog', ['cat', 'dog', 'rat'])
is same as:['cat', 'dog', 'rat'].indexOf('dog')
You can animate things with jQuery like this:$('.element').fadeIn()
$('.element').animate({left: '20px'})
$('.element').stop()
There are no direct JavaScript alternatives to jQuery’s animation functions but you should use CSS animations anyway.
Appending elements:$('.element').append('<b>2nd element</b>')
Doing exactly the same in JavaScript is a little bit tricky. However you can do most of this kind of stuff with setting innerHTML-property.var el = document.createElement('b');
el.innerHTML = '2nd element';
document.querySelector('.element').append(el);
So we already saw this on the previous point:$('.element').html('<b>2nd element</b>')
And alternatively:document.querySelector('.element').innerHTML = '<b>2nd element</b>'
You can easily check element visibility in jQuery by:$('.element').is(":visible")
There is no direct alternative to this on pure JavaScript. Solution depends on how you have hidden your element. You can use for example one of these:document.querySelector('.element').style.display == 'none'
document.querySelector('.element').classList.contains('hidden')
Lastly making an ajax request:$.ajax({
++url: url,
++success: function(response) {
++++console.log(response);
++}
);
You can use native XMLHttpRequest to do the request:var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
++if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
++++console.log(xmlhttp.responseText);
++}
}
xmlhttp.open("GET", url, true);
xmlhttp.send();