@lopatnov/callable

Abstract class Callable is abstraction for creating new instances of a class as functions, not objects

Usage no npm install needed!

<script type="module">
  import lopatnovCallable from 'https://cdn.skypack.dev/@lopatnov/callable';
</script>

README

@lopatnov/callable Twitter

npm NPM version License GitHub issues GitHub forks GitHub stars Build Status

Patreon sobe.ru LinkedIn

Abstract class Callable is abstraction for creating new instances of a class as functions, not objects.

Install

https://nodei.co/npm/@lopatnov/callable.png?downloads=true&downloadRank=true&stars=true

npm install @lopatnov/callable

Browser

<script src="//lopatnov.github.io/callable/dist/byBind.min.js"></script>
<script src="//lopatnov.github.io/callable/dist/byCallee.min.js"></script>
<script src="//lopatnov.github.io/callable/dist/byClosure.min.js"></script>
<script src="//lopatnov.github.io/callable/dist/byProxy.min.js"></script>

Import package to the project

TypeScript package import

import Callable from "@lopatnov/callable"; // byBind

or

import CallableByBind from "@lopatnov/callable/dist/byBind";
import CallableByCallee from "@lopatnov/callable/dist/byCallee";
import CallableByClosure from "@lopatnov/callable/dist/byClosure";
import CallableByProxy from "@lopatnov/callable/dist/byProxy";

JavaScript package import

var Callable = require("@lopatnov/callable"); // byBind

or

var CallableByBind = require("@lopatnov/callable/dist/byBind");
var CallableByCallee = require("@lopatnov/callable/dist/byCallee");
var CallableByClosure = require("@lopatnov/callable/dist/byClosure");
var CallableByProxy = require("@lopatnov/callable/dist/byProxy");

How to use

TypeScript usage

import Callable from "@lopatnov/callable";

class ChildCallable extends Callable<string> {
  _call(...args: any[]): string {
    return `Hello ${args[0]}`;
  }
}

let x = new ChildCallable(); // <-- returns function
let xc = x("World"); // <-- calls _call function of ChildCallable class

console.log(xc); // "Hello World"

JavaScript usage

var Callable = require("@lopatnov/callable");

class ChildCallable extends Callable {
  _call(...args) {
    return `Hello ${args[0]}`;
  }
}

let x = new ChildCallable(); // <-- returns function
let xc = x("World"); // <-- calls _call function of ChildCallable class

console.log(xc); // "Hello World"

Description of abstract class Callable<TResult> and it's variations

Abstract class Callable has different realizations. They have different plus side and minus side.

The parameter TResult is a result type of a function.

abstract class CallableByBind<TResult>

This is the function bind way.

Plus side

  • Doesn’t rely on deprecated or modern features.
  • No need to modify prototypes.

Minus side

  • Requires wrapping the function object in a bound function.

abstract class CallableByCallee<TResult>

Plus side

  • Very simple.
  • No need to modify prototypes.

Minus side

  • arguments and arguments.callee are unavailable in ‘strict mode’, see MDN for more.

abstract class CallableByProxy<TResult>

Plus side

  • Simple, native way to intercept calls and redirect them.
  • No need to modify prototypes.

Minus side

  • Requires wrapping objects created by Callable in a Proxy.
  • A small performance penalty for using Proxy handlers.

abstract class CallableByClosure<TResult>

Plus side

  • Requires no wrapping of the returned object with a Proxy or bind.

Minus side

  • Requires modifying prototypes.
  • Modifying prototypes is slow and has other side effects, see MDN.

Demo

See, how it's working: https://runkit.com/lopatnov/callable-demo

Test it with a runkit: https://npm.runkit.com/@lopatnov/callable

Rights and Agreements

License Apache-2.0

Copyright 2019-2021 Oleksandr Lopatnov