2

How can I return __plugin inside add and css function without return __plugin inside them. Can I use a higher order function? Everything is working as expected but I would like to know and maybe refactor this code.

I don't want to write return __plugin every time only one time.

const $ = (el) => {
  let _plugin = {};
  const element = document.querySelector.bind(document);
  const css = (style) => {
    Object.assign(element(el).style, style)
    return _plugin;
  }
  const add = (c) => {
    element(el).classList.add(c)
    return _plugin;
  }
  _plugin = { add, css }
  return  _plugin
}

Thank you.

9
  • 1
    So you want to return __plugin and you don't want to return __plugin? Commented Apr 19, 2017 at 2:20
  • yeah... what you wrote is just weird. Still, what about using a callback function? the callback could get __plugin as a parameter... Javascript people love them callbacks Commented Apr 19, 2017 at 2:21
  • @SpencerWieczorek yes I don't want to write return __plugin every time . I just want to know if there is a better way. Commented Apr 19, 2017 at 2:22
  • Why do you need to return an empty object within the first two expressions anwyway? You're not actually modifying it until after the expressions. Commented Apr 19, 2017 at 2:32
  • 1
    @Derek—the $ function returns an object with add and css methods. The OP wants to be able to chain function calls, e.g. $('#foo').add(className).css({backgroundColor: 'red'}); Commented Apr 19, 2017 at 2:37

3 Answers 3

2

You can create a higher-order function which wraps around each of the functions in your _plugin object, and it will make all of your functions chainable.

const chainable = (obj) => {
  for (const key in obj) {
    const func = obj[key];
    if (typeof func === 'function') {
      obj[key] = function () {
        const val = func.apply(this, arguments);
        return val === undefined ? this : val;
      };
    }
  }
  return obj;
};

const $ = (el) => {
  const element = document.querySelector(el);
  const css = (style) => {
    Object.assign(element.style, style);
  };
  const add = (c) => {
    element.classList.add(c);
  };
  return chainable({ add, css });
};

/* Testing code */

$('#test')
  .add('testClass')
  .css({ 'background-color': 'black' });
.testClass { color: red; }
<div id="test">Testing</div>

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

6 Comments

Thank. Is there a similar function in lodash or ramda?
@jonathandion I don't know of one, but you could certainly use those libraries to simplify the code for chainable. _.functionsIn(obj).forEach could replace the for in loop and if statement.
Amazing stuff I refactored your code: jsfiddle.net/jondion/f1uc7v9p/7 What do you think?
@jonathandion That looks good. For reliability's sake, I didn't use func.name because it's not necessarily the same as the key in the object (see the documentation for Function.name).
Yes, exactly I was reading the code again and same thought. I updated the code. I would like to D.M you for further questions. Thanks.
|
1

I'm assuming you want to attach objects to those variables with something like this:

const $ = (el) => {
    const element = document.querySelector.bind(document);
    const css = (style) => {
        Object.assign(element(el).style, style);
    };
    const add = (c) => {
        element(el).classList.add(c);
    };

    return {add, css};
};

Otherwise you'd just be returning undefined objects since plugin is never manipulated (or dependent on multiple conditions rather).

1 Comment

The idea is to chain calls, so each function has to return the _plugin object. It's not undefined, it has add and css methods which have a closure to element.
1

Based on the comments.. you could do a minor refactor like so:

const $ = (el) => {
   const element = document.querySelector.bind(document);

   const css = function(style) {
    Object.assign(element(el).style, style)
    return this;
   }

   const add = function(c) {
    element(el).classList.add(c)
    return this;
   }

   return  { add, css };
};

If you want to get rid of using plugin and keep the ability to chain, swap out the inner arrow function for regular functions. This allows you to return this which is scoped to $.

1 Comment

this is never bound to "where ever [a function] was called from". It's set by the call, bind or lexically for arrow functions.

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.