DEV Community

Cover image for Make your own jQuery from scratch
Joydeep Bhowmik
Joydeep Bhowmik

Posted on Edited on

Make your own jQuery from scratch

jQuery is one of the most popular JavaScript library . It greatly simplifies JavaScript programming. You might be curious about how jQuery is made. If you look through the source code of any well-known library, it's likely that you won't understand anything or you may feel that you need to be a genius to build one. However, it's not as difficult as it seems in reality. In this article I'm going show you how you can make your own library like jQuery from scratch.

Lets get started!

Creating the selector function

const $ = function(el) {
    return new jQuery(el);
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

As you can see the selector function returns a class named jQuery. Every time you use the selector a new instance of jQuery will be created .

Now lets create our jQuery Class

jQuery object

 class jQuery extends Array{
    constructor(el) {
        super();
        if (el == document || el instanceof HTMLElement) {
            this.push(el);
        } else {
            let elements=document.querySelectorAll(el);
            for(let i=0;i<elements.length;i++){
                this.push(elements[i]);
            }
        }
    }
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

Our jQuery class extends the build-in Array class so every instance behave like an array and an object at the same time.Every time we create a new jQuery instance it checks if the element is html element or if it is the document itself. If not then it performs a querySelectorAll to get the all matched elements. Then it pushes each element to itself. Now we can add our methods to it.

Chaining

The best thing I like about jQuery is that you can chain methods, like

$('div').addClass('red').html('hello');
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

to apply Chaining to our jQuery class we just need to return the current instance, i.e adding
return this after every method.

ready()

ready(callback){
    this[0].addEventListener('readystatechange', e => {
        if(this[0].readyState === "complete"){
            callback();
            return true;
        }
      });
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
$(document).ready(function(){
 //codes
})
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

Checks the readyStates of an element if the readyState is complete than we know the element is completely loaded and ready for use;

each()

    each(callback) {
        if (callback && typeof(callback) == 'function') {
            for (let i = 0; i < this.length; i++) {
                callback(this[i], i);
            }
            return this;
        } 
    }
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
$('div').each(function(el){
    $(el).html('text')
})
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

this method iterate over all elements and give a callback for each element. We will use this for creating other methods.

siblings()

siblings(){
    return  [...this[0].parentNode.children].filter(c=>c!=this[0])
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
console.log($('script').siblings())
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

It's a pretty simple one liner. We first select all the child elements of parent element and then just remove the current element from the list , resulting an array of sibling elements.

addClass()

addClass(className) {
    this.each(function(el) {
        el.classList.add(className);
    })
    return this;
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
$('div').addClass('pink')
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

we use classList.add() to add the className to each item with the help of this.each method.

removeClass()

removeClass(className) {
    this.each(function(el) {
        el.classList.remove(className);
    })
    return this;
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
$('div').removeClass('pink')
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

similar to addClass we use classList.remove() to remove the className .

hasClass()


hasClass(className) {
    return this[0].classList.contains(className);
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
console.log($('div').hasClass('pink')) //returns true or false
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

hasClass check if the 1st selected element has any specific class with the help of classList.contains() and return true or false accordingly.

css()

 css(propertyObject) {
       this.each(function(el) {
           Object.assign(el.style,propertyObject);
        })
        return this;
    }
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
$('div').css({
    color:'red'
})
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

in this method the parameter is a type of object. each property of this object is added to the element.style object using in-build Object.assign function()

attr()

attr(attr, value = null) {
    let getattr = this;
    if (value){
        this.each(function(el) {
            el.setAttribute(attr, value);

        });
    } else {
            getattr = this[0].getAttribute(attr);
    }
    return getattr;
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
console.log($('div').attr('class')) //gets the attribute value
$('div').attr('name','div') //sets the name attribute with value
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

If the value argument is not present then we just simple return the attribute value else we set the attribute for each element.

html()

html(data) {
    if (data) {
        this.each(function(el) {
            el.innerHTML = data;
        })
    } else {
        return this[0].innerHTML;
    }
    return this;
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
console.log($('div').html()) //gets the innerHTML 
$('div').html('x') //add the innerHTML
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

Similar to attr() method just uses innerHTML instead of attribute

prepend()

prepend(el){
    this[0].prepend(el);
    return this;
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
let h1=document.createElement('h1');
h1.innerHTML='this is a heading';
$('div').prepend(h1) //prepend the node
$('div').prepend('hello') //prepend the string 
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

prepend a node or string to the selected elements using in-build node.prepend().

append()

append(el){
    this[0].append(el);
    return this;
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
let h1=document.createElement('h1');
h1.innerHTML='this is a heading';
$('div').append(h1) //append the node
$('div').append('hello') //append the string
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

append a node or string to the selected elements using in-build node.append().

hide()

hide() {
    this.each(function(el) {
        el.style.display = "none";
    });
    return this;
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
$('div').hide()
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

change the style.display property to none

show()

show() {
    this.each(function(el) {
        el.style.display = "block";
    });
    return this;
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
$('div').show()
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

change the style.display property to block

on()

on(event, child, callback = null) {
    if (callback != null) {
        let selector = child;
        this.each(function(element) {
            element.addEventListener(event, function(event) {
                if (event.target.matches(selector + ', ' + selector + ' *')) {
                    callback.apply(event.target.closest(selector), arguments);
                }
            })
        })
    } else {
    //if the callback argument is not present then assume  the child argument is being use as callback
        callback = child;
        this.each(function(element) {
        element.addEventListener(event, callback);
        })
    }

    return this;
}
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
$('div').on('click',function(){
    alert('x')
})
$(document).on('click','div',function(){
    alert('x')
})
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

this one is little bit complex.
If we pass all three arguments to the method it will add an EventListener to the parent element and only if the target matches child element then will give a callback.

but if we just pass two argument then it will simply add an EventListener to the element with a callback.

for the first case we can take this as an example

$(document).on('click','div',function(){
    alert('x')
})
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

and for the second case

$('div').on('click',function(){
    alert('x')
})
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

both serves their different purpose . First one is very useful for binding event to dynamic element.
Second one is useful for general event binding .

$.ajax()

$.ajax=function(args) {
        let url = args["url"];
        let type = "get";
        let success =function(){};
        let fail = function(){};
        if(args['success']){
            success=args['success'];
        }
        if(args['fail']){
            fail=args['fail'];
        }
        let xhttp = new XMLHttpRequest();
        xhttp.onerror = function(error){
        //return fial callback with error 
            return fail(error);
        }
        xhttp.onload = function() {
            let response;
            if (this.readyState == 4 && this.status == 200) {
                let response="";
                try {
                //check if the response in json 
                //if json the parse it
                    response=JSON.parse(this.responseText)
                } catch (e) {
                //if not json the simple reurn the response
                    response = this.responseText;
                    }
                 // give a success callback
                return success(response);
            } else {
            //give a fail callback with the error status 
                return fail(this.status);
            }
        };
        let parameters="";
        if (args) {
            type = args["type"];
            if ('data' in args) {
            //converting object to url URLSearchParams
                parameters = new URLSearchParams(args['data']).toString();
            }

        }
        if (type && type.toUpperCase()=='POST') {
            xhttp.open("POST", url, true);
            xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhttp.send(parameters);
        } else if (!type || type.toUpperCase()=='GET'){
            xhttp.open("GET", url + "?" + parameters, true);
            xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            xhttp.send();
        }
    }
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
$.ajax({
    url:'post.php',
    type:'post',
    data:{
        name:'Joydeep'
    },
    success: function(res){
        console.log(res)
    }
})
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

this ajax function is not a method but works as a property of $ object.
this function takes url,type,data,success and fail arguments just like the original jQuery.
What we do is that we create a new new XMLHttpRequest() each time the function is called and send post or get request. Now if we receive the response then we check if it is JSON response.For JSON response we parse it otherwise just simply return a success callback with the response.But if request gives a error, fail callback with the status code will be returned.

Putting it all together

class jQuery extends Array{
    constructor(el) {
        super();
        if (el == document || el instanceof HTMLElement) {
            this.push(el);
        } else {
            let elements=document.querySelectorAll(el);
            for(let i=0;i<elements.length;i++){
                this.push(elements[i]);
            }
        }
    }
    ready(callback){
        this[0].addEventListener('readystatechange', e => {
            if(this[0].readyState === "complete"){
                callback();
                return true;
            }
          });
    }
    each(callback) {
        if (callback && typeof(callback) == 'function') {
            for (let i = 0; i < this.length; i++) {
                callback(this[i], i);
            }
            return this;
        } 
    }
    siblings(){
        return  [...this[0].parentNode.children].filter(c=>c!=this[0])
    }
    addClass(className) {
        this.each(function(el) {
            el.classList.add(className);
        })
        return this;
    }

    removeClass(className) {
        this.each(function(el) {
            el.classList.remove(className);
        })
        return this;
    }

    hasClass(className) {
        return this[0].classList.contains(className);
    }

    css(propertyObject) {
        this.each(function(el) {
            Object.assign(el.style,propertyObject);
        })
        return this;
    }

    attr(attr, value = null) {
        let getattr = this;
        if (value) {
            this.each(function(el) {
                el.setAttribute(attr, value);

            });
        } else {
            getattr = this[0].getAttribute(attr);
        }
        return getattr;
    }

    html(data) {
        if (data) {
            this.each(function(el) {
                el.innerHTML = data;
            })
        } else {
            return this[0].innerHTML;
        }
        return this;
    }
    append(el){
        this[0].append(el);
        return this;
    }
    prepend(el){
        this[0].prepend(el);
        return this;
    }
    hide() {
        this.each(function(el) {
            el.style.display = "none";
        });
        return this;
    }
    show() {
        this.each(function(el) {
            el.style.display = "block";
        });
        return this;
    }
    on(event, child, callback = null, state = null) {
        if (callback != null) {
            let selector = child;
            this.each(function(element) {
                element.addEventListener(event, function(event) {
                    if (event.target.matches(selector + ', ' + selector + ' *')) {
                        callback.apply(event.target.closest(selector), arguments);
                    }
                }, false)
            })
        } else {
            callback = child;
            this.each(function(element) {
                if (state) {
                    element.addEventListener(event, callback, state);
                } else {
                    element.addEventListener(event, callback, false);
                }
            })
        }

        return this;
    }
}
const $ = function(el) {
    return new jQuery(el);
}
$.ajax=function(args) {
        let url = args["url"];
        let type = "get";
        let success =function(){};
        let fail = function(){};
        if(args['success']){
            success=args['success'];
        }
        if(args['fail']){
            fail=args['fail'];
        }
        let xhttp = new XMLHttpRequest();
        xhttp.onerror = function(error){
            return fail(error);
        }
        xhttp.onload = function() {
            let response;
            if (this.readyState == 4 && this.status == 200) {
                let response="";
                try {
                    response=JSON.parse(this.responseText)
                } catch (e) {
                    response = this.responseText;
                    }
                return success(response);
            } else {
                return fail(this.status);
            }
        };
        let parameters="";
        if (args) {
            type = args["type"];
            if ('data' in args) {
                parameters = new URLSearchParams(args['data']).toString();
            }

        }
        if (type && type.toUpperCase()=='POST') {
            xhttp.open("POST", url, true);
            xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhttp.send(parameters);
        } else if (!type || type.toUpperCase()=='GET'){
            xhttp.open("GET", url + "?" + parameters, true);
            xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            xhttp.send();
        }
    }
⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026 ⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026

Now you have your own jQuery library. Of course the Original jQuery have more methods and good optimization but this is enough for regular tasks.

IF you are interested in this type of posts please check out my
blog

Read next
Virtual Dom Diffing Algorithm Implementation In Vanilla JavaScript

Top comments (2)

⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
 
fruntend profile image
fruntend •

Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up 👍

⭐ Football Update: joydeep bhowmik/make your own jquery from scratch mh - Info Live Streaming 2026
 
joydeep-bhowmik profile image
Joydeep Bhowmik • • Edited

Thank you ☺️☺️☺️☺️