Search code examples
javascriptjqueryselectors-api

Mimicking $ jQuery selector with forEach yields undefined


I know there are a lot of lightweight JavaScript libraries that do the job, but for my curiosity, I tried this:

function $(a) {

    b = document.querySelectorAll(a);

  [].forEach.call(b, function(d) {

    return d

  });
}

$(".tobered,#illbered").style.border = '1px solid #f00'

And of course my console said: TypeError: $(...) is undefined.

Lets do clearer :

Simplified 'function' :

var $ = document.querySelectorAll.bind(document)

Call which works :

$(".tobered,#illbered")[0].style.border = '1px solid #f00'

Call I need but in one line :

 $(".tobered,#illbered")[0].style.border = '1px solid #f00'
 $(".tobered,#illbered")[1].style.border = '1px solid #f00'
 $(".tobered,#illbered")[2].style.border = '1px solid #f00'
 $(".tobered,#illbered")[...].style.border = '1px solid #f00'

Clearer

How does this works ? https://api.jquery.com/multiple-selector/

Can't figure it out by reading the jquery.js file


Solution

  • There's a conceptual misunderstanding there.

    $ is declared but its return value is undefined. It doesn't return anything. Therefore you can't do undefined.style.

    But even if it returned something, you would be accessing the style property of whatever it returned. The function has already been executed at that point.

    function $(a) {
        b = document.querySelectorAll(a);
        //Calling forEach of an empty array
        //              Each call with b as this
        //                 And the function as parameter
        [].forEach.call(b, function(d) {
            //This actually will never run because there're no elements
            //But if it did, d would be returned to the forEach call
            //and forEach wouldn't do anything with the returned value
            return d
        });
        //The forEach calls returned nothing
        //Function ended and nothing is returned
    }
    var r=$(...);
    //r $(...) is undefined
    

    Note that jQuery uses methods to achieve this, for example

    $(a).style(b);
    

    Where $(a) returns an object, and the method of the returned object style() applies the styles b to the selected elements, which are also defined somewhat in the returned object.

    So the way to do what you want would be to return some object in $() with properties and methods to apply the styles. Or to have a single function that does everything like $(selector,styles), or two functions, one $() to select (or just use querySelectorAll) and style() that does the forEach thing (like style(elems,styles)).