Giter VIP home page Giter VIP logo

custom-function's Introduction

custom-function

Coverage Status build status

Social Media Photo by Aaron Huber on Unsplash

Literally the only sane way, if not the fastest one, to extend the Function class without evaluation.

// const CustomFunction = require('custom-function');
import CustomFunction from 'custom-function';

class MyFunction extends CustomFunction {
  invoke(...args) {
    return this(...args);
  }
  toString() {
    return '[native code]';
  }
}

const cf = new MyFunction((a, b) => a + b);
cf(1, 2);         // 3
cf.invoke(1, 2);  // 3
cf.toString();    // "[native code]"

Why using a Class?

Object.assign(fn, {...extras}) can augment fn but it cannot have accessors, private fields, super.method(...args) calls, and so on, while with this module, everything possible with classes is possible with functions too.

Object.defineProperties can have accessors and not all enumerable and writable fields, but it still cannot set private fields or allow super.method(...args) calls.

On top of these limitations, adding O(n) features requires more effort than swapping once the prototypal chain, where the original Function.prototype root of the chain will be preserved regardless.

As summary: every solution to date that is not based on native class extends feature is somehow limited, likely slower, surely inferior in terms of DX.

Why only Function?

While writing this I had Function as one problematic constructor that cannot be extended due inevitable code evaluation involved while invoking super() but it's true that this approach/pattern can be used for any constructor that could be problematic if invoked right away, which is why there is a custom-function/factory export too so that anything becomes possible, example:

// const custom = require('custom-function/factory');
import custom from 'custom-function/factory';

// reproduce exactly what this module provides:
const CustomFunction = custom(Function);
class MyFunction extends CustomFunction {}

// go wild with any illegal constructor too
const Div = custom(HTMLDivElement);
class MyDiv extends Div {
  constructor(...childNodes) {
    super(document.createElement('div'));
    this.append(...childNodes);
  }
}

document.body.appendChild(
  new MyDiv(
    new MyDiv('A'),
    new MyDiv('B', 'C')
  )
);

Exports

  • custom-function to extend functions without invoking Function
  • custom-function/factory to extend any class without invoking the extended class constructor
  • custom-function/closure to extend functions in a Closure Compiler friendly way
  • custom-function/closure-factory to extend any class in a Closure Compiler friendly way

Performance

The benchmark test properties added to a callback using this module VS using a predefined descriptors object via Object.defineProperties to compare the most possible perf-tuned define properties approach against this module pattern.

Use npm run bench to test yourself locally, after cloning this repo.

cold run
CustomFunction
  creation: 20.884ms
  metohd: 3.421ms
Object.defineProperties
  creation: 76.917ms
  metohd: 4.838ms

hot run
CustomFunction
  creation: 7.597ms
  metohd: 0.667ms
Object.defineProperties
  creation: 94.064ms
  metohd: 1.359ms

custom-function's People

Contributors

webreflection avatar

Stargazers

Patrick G avatar Wesley Luyten avatar PJ Eby avatar Dan Cecile avatar Bryden Wayne avatar Papi Peppers avatar  avatar Luiz Felipe Warmling Amadeu avatar Jérémie Zarca avatar Hendry Sadrak avatar Rafael Bardini avatar Mohammed Hamdy avatar Nikita avatar Fabio Spampinato avatar Hamed Fathi avatar Evgeny avatar  avatar Mark Chris Levy avatar Daniel Kloimwieder avatar Hatem Hosny avatar Tom Byrer avatar Hyeseong Kim avatar Wired Earp avatar Jay avatar Eddy Recio avatar Matthew avatar David Trejo avatar  avatar Jonas Galvez avatar Duc-Thien Bui avatar Andrew Chou avatar  avatar

Watchers

 avatar James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.