1.1.1 • Published 9 years ago
extensible-function v1.1.1
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/.constructorreturn 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 itExtensibleFunctionor 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; //trueExtensibleFunction.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