Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

tiny implementation of jquery

1) I have a task to implement jQuery on Javascript. But for some reason my method each doesn't work. For example when i write

$('.a').each(function (index) {$(this).append('<b>' + index + '</b>')})

it returns

DOMException: Failed to execute 'querySelectorAll' on 'Document': '[object Object]' is not a valid selector.

also I can't use this.each inside of other functions. For example if I would have used each instead of forEach inside append it would have not worked.


<script type="text/javascript">
(function() {
  function $(selector) {
    if (this instanceof $) return this.search(selector)
      return new $(selector);
  }
  $.prototype = {
    constructor: $,
    length: 0,

    search: function(selector) {
      var that=this;
      var elems=Array.prototype.slice
          .call(document.querySelectorAll(selector));
      elems.forEach(function(x,i){that[i]=x;});
      this.length = elems.length;
      return this;
    },

    append: function(text) {
      if (text instanceof $) {
        this[0].appendChild(text[0]);
        for(var i = 1; i < this.length-1; i++) {
          var p = text[0].cloneNode(true);
          this[i].appendChild(p);
        }
      } else Array.prototype.slice
          .call(this).forEach(function(x){
              x.innerHTML  =  x.innerHTML  +  text;
          });

      return this;
    },  

    each: function(callback){
      for (var i=0;i<this.length;i++){
        this[i]=callback.call(this,this[i])
      };
      return this;
    },

  }
  window.$ = $;
}());

like image 868
Aleks Avatar asked Apr 15 '15 11:04

Aleks


1 Answers

For example when i write

$('#id').each(function (index) {$(this).html('<b>' + index + '</b>')})

it returns

DOMException: Failed to execute 'querySelectorAll' on 'Document': '[object Object]' is not a valid selector.

You're doing $(this) inside your each callback. So that calls $ with this set to the DOM element, which is not instanceof $, and so you call new $(selector) passing the DOM element. That ends up calling this.search(selector) where, again, selector is the DOM element. Then you call querySelectorAll(selector). QSA accepts strings, not DOM elements, and so the element gets converted to the string "[object Object]" (or on some engines it'll be "[object HTMLElement]"), and fails.

You can diagnose these errors by walking through the code statement-by-statement using the debugger built into your browser. If you're going to reimplement jQuery for some reason, you'll need to get in the habit of doing exactly that: Using the debugger heavily, identifying what's wrong, and fixing it.

In this case, for instance, you'll want to detect that selector is not a string and handle that, e.g. something vaguely like this:

search: function(selector) {
  var that=this, elems;
  if (typeof selector === "string") {
    elems = Array.prototype.slice.call(document.querySelectorAll(selector));
    elems.forEach(function(x,i){that[i]=x;});
    this.length = elems.length;
  } else {
    this[0] = selector;
    this.length = 1;
  }
  return this;
},

But there will be lots and lots of other things you'll run into beyond that, which you'll need your debugger for.

like image 136
T.J. Crowder Avatar answered Sep 30 '22 07:09

T.J. Crowder