3

My goal is to replicate the normal jQuery each type function from scratch using only Javascript. Here is my code so far:

// Created a jQuery like object reference
function $(object) {
    return document.querySelectorAll(object);

    this.each = function() {
        for (var j = 0; j < object.length; j++) {
            return object[j];
        }
    }

}

console.log($('.dd')); // returns NodeList[li.dd, li.dd]

$('.opened').each(function() {
    console.log(this);
}); // Results in an error [TypeError: $(...).each is not a function]

As you can see, each is showing as a error. How should I go about fixing this?

Shivam
  • 2,208
  • 3
  • 24
  • 39
  • why reinvent the wheel? – Mohammad Areeb Siddiqui Jul 06 '13 at 13:47
  • 2
    Are you asking something? –  Jul 06 '13 at 13:48
  • @steo: what do you consider to be the 'jQuery selector'? And assuming it's the `$`, why *not* use an easily-typed, short variable name for a function that'll be used repeatedly? – David Thomas Jul 06 '13 at 13:50
  • why loop over an string and try to call methods on it ? – VeXii Jul 06 '13 at 13:52
  • 1
    @Mohammad, I have a school assignment for my Javascript class and I am not allowed to use jQuery, which is why I am attempting to create my own simple functions similar to jQuery. – Shivam Jul 06 '13 at 14:00
  • @ShivamBhalla then you are doing a big mistake! why you are creeating jQuery just create a simple function like each! don't reinvent jQuery! – Mohammad Areeb Siddiqui Jul 06 '13 at 14:01
  • @Mike W, sorry, I updated the post with my question. – Shivam Jul 06 '13 at 14:01
  • @ShivamBhalla what about this: http://jsfiddle.net/AP8Np/ – Mohammad Areeb Siddiqui Jul 06 '13 at 14:03
  • @Mohammad Thanks for your input. I totally agree with you but I also want to understand some other concepts, such as creating a function as an argument to another function etc... We have learned the very very basics and I would like to try to learn more on my own. – Shivam Jul 06 '13 at 14:04
  • 1
    See the 'Compatibility' section at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach for some ideas. You might find https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide useful if you are new to JavaScript. – 1983 Jul 06 '13 at 14:18
  • @ NagaJolokia, thanks for the tip. I will definitely do that. – Shivam Jul 06 '13 at 14:42

2 Answers2

4

A lightweight class that works like that would be:

function $(selector) { 
    // This function is a constructor, i.e. mean to be called like x = new $(...)
    // We use the standard "forgot constructor" trick to provide the same
    // results even if it's called without "new"
    if (!(this instanceof $)) return new $(selector);

    // Assign some public properties on the object
    this.selector = selector;
    this.nodes = document.querySelectorAll(selector);
}

// Provide an .each function on the object's prototype (helps a lot if you are
// going to be creating lots of these objects).
$.prototype.each = function(callback) {
    for(var i = 0; i < this.nodes.length; ++i) {
        callback.call(this.nodes[i], i);
    }
    return this; // to allow chaining like jQuery does
}

// You can also define any other helper methods you want on $.prototype

You can use it like this:

$("div").each(function(index) { console.log(this); });

The pattern I 've used here is widely known (in fact jQuery itself also uses it) and will serve you well in a great many cases.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • Thats great!, works perfectly! Questions: 1. Inside the $(selector) function, what exactly does line 2 do? Also how do you manage to reference 'this' correctly? When I tried to reference 'this' inside my function, it referred to the index.html file. 2. $.prototype, I have trouble grasping the concept of the prototype method. Can you also briefly explain how it works? – Shivam Jul 06 '13 at 14:13
  • Really nice and well explained +1 – Roko C. Buljan Jul 06 '13 at 14:15
  • @ShivamBhalla: Look at the commends I added. The difference is that your code did not use `new` when calling the function. The first line in the function makes sure that if someone calls `$(x)` instead of `new $(x)` we correctly call `new $(x)` and return that. You have to use `new` to make `this` point to the instance, otherwise you saw what happens. – Jon Jul 06 '13 at 14:18
  • @ShivamBhalla: There is a lot of material to cover your questions regarding `new` and object prototypes in JS, much more and also much better than I could write here. Search SO and google, for example http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript – Jon Jul 06 '13 at 14:21
  • Thanks so much for all your help! This really gives me the tools to create so much more and learn more about how these methods work. Cant explain how much this will help me in the future :) thanks again! – Shivam Jul 06 '13 at 14:35
1

something like this...??

function $(object) {
    var obj = {
        arr : document.querySelectorAll(object),
        each : function(fun){
            for (var i = 0; i < this.arr.length; i++) {
                fun.call(this, this.arr[i]);
            }
        }
    }
    return obj;
}
mohkhan
  • 11,925
  • 2
  • 24
  • 27