3

I am trying to understand how to work jQuery and other libraries. I would like to know how to create a selector with this format:

$("#selector").get(); 

By the moment, I am trying the next, but i don't know how to run internal functions (get(), set()):

var $ = (function() {

    var jQuery = {
        get: function() {
            console.log("get() function!!");
            return this;
        },
        set: function() {
            console.log("set() function!!");
            return this;
        }
    };

    return function(el) {
        return document.querySelector(el);
    }       
})();

I have read something about modular pattern design in JavaScript, but I don't understand all.

4
  • 1
    Modify jQuery.fn, an alias for the prototype Commented Jul 8, 2017 at 20:46
  • And if you want to add multiple functions, you can use $.fn.extend($.fn, {...}). Commented Jul 8, 2017 at 20:48
  • Sorry, I'm not writting a jQuery plugin, I'm trying to write a "library" and learn. Commented Jul 8, 2017 at 20:52
  • Read the source ... Commented Jul 8, 2017 at 20:53

3 Answers 3

6

The way to make chainable functions, is to first and foremost create instances with the new keyword.

This can be done "automatically" by making sure the this value of the called function is an instance of itself, if not explicitly call it with new.

Then it's just a matter of returning the instance and using prototyped methods.

var $ = function(selector) {
  if (! (this instanceof $) ) {
    return new $(selector);
  }
  this.el = document.querySelectorAll(selector);
  return this;
}

$.prototype.css = function(prop, val) {
  this.el.forEach(function(element) {
    element.style[prop] = val;
  });

  return this;
}

$('#test').css('color', 'red').css('font-size', '30px')
<div id="test">test</div>

Sign up to request clarification or add additional context in comments.

6 Comments

Remember that jQuery does a lot more things than simply document.querySelectorAll(selector);. It activelly avoids it for ids (recurring to document.getElementById();) and, with some care, for tags too (using document.getElementsByTagName();). Not to mention all the pseudo-selectors.
@IsmaelMiguel - of course it does, jQuery is 250 000 bytes (not minimized), so it does a whole lot of things (...all things). This answer is just to show how chainable methods work, not how the entire jQuery library works.
Yes, but the comment is just to tell to curious readers that jQuery isn't just simply using document.querySelectorAll(selector); with a bunch gimmicks on top.
@IsmaelMiguel - no, for the "curious reader", it does this, unfortunately copying the entire init code of jQuery doesn't make for a very good answer.
@codeWithMe - no it does not! When you write it like I did above, there's no colon. You can either pass in two arguments, seperated by a comma, as in my answer, or you pass in an object, as in your comment, it's up to you.
|
0
const $ = function(selector) {
    if (!(this instanceof $)) {
        return new $(selector);
    };
    this.el = document.querySelectorAll(selector);
};
$.prototype.css = function(obj) {
    this.el.forEach(function(element) {
        element.style[Object.keys(obj)[0]] = Object.values(obj);
    });
};
$.prototype.click = function(callback) {
    this.el.forEach(function(element) {
        element.addEventListener('click', callback, false);
    });
};

Comments

0

jQuery this or $(selector) is array like [div, div] not object {el: [div, div]}, so its not using this.el to modified the elements, here simplified version

if (window.$ === undefined) window.$ = (function () {
    var $, fun = {}, emptyArray = [];

    function Z(dom, selector) {
        var i, len = dom ? dom.length : 0;
        for (i = 0; i < len; i++) this[i] = dom[i];
        this.length = len;
        this.selector = selector || '';
    }
    fun.Z = function (dom, selector) {return new Z(dom, selector);};
    fun.init = function (selector, context) {
        if (!selector) return fun.Z();
        var dom = document.querySelectorAll(selector);
        return fun.Z(dom, selector);
    };
    Z.prototype = {
        splice: emptyArray.splice,
        forEach: emptyArray.forEach,
        html: function (str) {
            return this.forEach(function (el) {
                el.innerHTML = str;
            });
        },
        css: function(obj, value){
          if(typeof obj == 'object'){ // like: .css({background: 'red'})
             for(var k in obj){
              return this.forEach(function (el) {
                el.style[k] = obj[k];
              });
            }
          }
          else{ // called: .css('background', 'red')
            return this.forEach(function (el) {
                el.style[obj] = value;
              });
          }
        }
    };
    $ = function (sel, ctx) {return fun.init(sel, ctx); };

    return $;
})();
<div class="test"> AAAA </div>
<div class="test"> BBBB </div>

<button onclick="$('.test').css({background: 'red'})">red</button>
<button onclick="$('.test').css('background', 'blue')">blue</button>
<br />
<button onclick="console.log($('.test'))">log to console</button>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.