extensible-function
v1.1.1
Published
An extensible ES6 function with idiomatic inheritance and various other benifits
Downloads
15
Maintainers
Readme
extensible-function
An extensible ES6 function with idiomatic inheritance and various other benifits:
Installation
npm install --save extensible-function
- When extending
ExtensibleFunction
, the code is idiomatic of extending any ES6 class (no, mucking about with pretend constructors or proxies). - The prototype chain is retained through all subclasses, and
instanceof
/.constructor
return the expected values. .bind()
.apply()
and.call()
all function as expected. This is done by overriding these methods to alter the context of the "inner" function as opposed to theExtensibleFunction
(or it's subclass') instance..bind()
returns a new instance of the functions constructor (be itExtensibleFunction
or a subclass). It usesObject.assign()
to ensure the properties stored on the bound function are consistent with those of the originating function.- Closures are honored, and arrow functions continue to maintain the proper context.
- The "inner" function is stored via a
Symbol
, which is obfuscated by the module.
ExtensibleFunction
Example of extending ExtensibleFunction
const ExtensibleFunction = require('extensible-function');
// OR //
import ExtensibleFunction from 'extensible-function';
// Lets extend our `ExtensibleFunction` into an `ExtendedFunction`
class ExtendedFunction extends ExtensibleFunction {
constructor (fn, ...args) {
// Just use `super()` like any other class
// You don't need to pass ...args here, but if you used them
// in the super class, you might want to.
super(fn, ...args);
// Just use `this` like any other class. No more messing with fake return values!
let [constructedPropertyValue, ...rest] = args;
this.constructedProperty = constructedPropertyValue;
}
}
Example of using the ExtendedFunction
let fn = new ExtendedFunction(function (x) {
// Add `this.y` to `x`
// If either value isn't a number, coax it to one, else it's `0`
return (this.y>>0) + (x>>0)
}, "I'm a constructed property value");
fn.additionalProperty = "I'm an additional property value";
This is what you get
fn instanceof Function; // true
fn instanceof ExtensibleFunction; //true
fn instanceof ExtendedFunction; //true
fn.bind() instanceof Function; //true
fn.bind() instanceof ExtensibleFunction; //true
fn.bind() instanceof ExtendedFunction; //true
fn.constructor == ExtendedFunction; //true
fn.constructedProperty == "I'm a constructed property value"; //true
fn.additionalProperty == "I'm an additional property value"; //true
fn.constructedProperty == fn.bind().constructedProperty; //true
fn.additionalProperty == fn.bind().additionalProperty; //true
fn() == 0; //true
fn(10) == 10; //true
fn.apply({y:10}, [10]) == 20; //true
fn.call({y:10}, 20) == 30; //true
fn.bind({y:30})(10) == 40; //true
ExtensibleFunction.Bound
The module also provides a convenient constructor which binds a function to itself. Yeah, it sounds weird but the benefit is that calls to these functions have their this
set to themselves.
Example of using ExtensibleFunction.Bound
class BoundExtendedFunction extends ExtensibleFunction.Bound {
constructor (fn, x) {
super(fn);
this.x = x;
}
}
let bfn = new BoundExtendedFunction(function(y){
return this.x + y;
}, 100);
bfn(42); // 142
bfn.x = 0;
bfn(42); // 42