Why are Higher Order Functions hiding my ES6 Class properties? - javascript

EDIT: I've added updated screenshots (at the end), for further clarification.
I'm attempting to use high order functions to compose subclasses/mixins but noticed I can only access the properties of the very first class I extend and can only access the properties of any subsequent classes after I've called the class. Here is a contrived example of what I mean:
These are functions that will apply subclasses to the parent class:
export const middleNameClass = middlename => BaseClass => {
return class extends BaseClass {
constructor(args) {
super(args);
this.middlename = middlename;
}
};
};
export const lastNameClass = lastname => BaseClass => {
return class extends BaseClass {
constructor(args) {
super(args);
this.lastname = lastname;
}
};
};
Here is firstNameClass, which will be extended directly by the parent class, Person:
class firstNameClass {
constructor(args) {
this.firstname = args;
}
}
This is Person, which extends firstNameClass:
class Person extends firstNameClass {
constructor(args) {
super(args);
this.getNames = this.getNames.bind(this);
// I'm using to log class properties to the console
this.getNames();
}
getNames() {
console.log("this inside getNames(): ", this);
console.log("firstnames inside getNames(): ", this.firstname);
console.log("middlenames inside getNames(): ", this.middlename);
console.log("lastnames inside getNames(): ", this.lastname);
}
}
and finally, here is where I apply my higher order functions and create my class:
const enhancedClass = compose(
middleNameClass("Allan"),
lastNameClass("Poe")
)(Person);
const namedPerson = new enhancedClass("Edgar");
However, I see the following when I check my console.log:
this.firstnames inside getNames(): Edgar
this.middlenames inside getNames(): undefined
this.lastnames inside getNames(): undefined
Could someone explain what I'm doing wrong?
EDIT:
Here are the contents of my Person class:
and here is what is output to the console, after I create the class:

At new enhancedClass('Edgar'), this happens:
lastNameClass's constructor calls super
middleNameClass's constructor calls super
Person's constructor calls super
firstNameClass does this.firstName = 'Edgar'
Return to Person, which calls getNames
Return to middleNameClass, which does this.middleName = 'Allan'
Return to lastNameClass, which does this.lastName = 'Poe'
Calling getNames afterwards should work. Same thing would've happened if you used extend every time.

This isn't an answer to your question but maybe it's a solution to your problem
JavaScript doesn't have multiple inheritance but luckily for you functional programming has nothing to do JavaScript's class system, object prototypes, or other object-oriented concepts. Functional programming is all about functions!
We begin writing our inheritable modules with some functions
// module 1
const hasFirstName = (firstName = "") => o =>
{
field (o, 'firstName', firstName)
}
// module 2
const hasMiddleName = (middleName = "") => o =>
{
field (o, 'middleName', middleName)
}
// module 3
const hasLastName = (lastName = "") => o =>
{
field (o, 'lastName', lastName)
}
We haven't defined field yet, but don't worry. Let's look at a somewhat more involved module next
// module 4
const nameable = (first, middle, last) => o =>
{
inherit (o, hasFirstName (first))
inherit (o, hasMiddleName (middle))
inherit (o, hasLastName (last))
method (o, 'getFullName', (self) => `${self.firstName} ${self.middleName} ${self.lastName}`)
method (o, 'sayHelloTo', (self, other) => `Hello ${other.getFullName ()}, my name is ${self.getFullName ()}`)
}
OK, so now we can see how some modules can be composed of other modules. Before we look at inherit and method, let's see how we'd use our module
const Person = (first, middle, last) =>
Obj (self => {
inherit (self, nameable (first, middle, last))
})
So maybe you're annoyed that I keep making stuff up in each new code paste, but this is a very powerful practice called wishful thinking
"Wishful Thinking" is a very powerful programming practice:
Before implementing a component you write some of the code that actually uses it. This way you discover what functions with what parameters you really need, which leads to a very good interface. You will also have some good test code for your component.
The idea is based on the fact that an interface's purpose is to simplify the code that uses the component, not to simplify the code that implements it.
Exercising this practice, we wished up this imaginary object system based on what we need it to do - not based on what JavaScript's object system is capable of.
Of course we expect that using our Person will be straightforward
const p1 =
Person ('Augusta', 'Ada', 'King-Noel', 166)
const p2 =
Person ('Gerald', 'Jay', 'Sussman', 71)
console.log (p1.sayHelloTo (p2))
// Hello Gerald Jay Sussman, my name is Augusta Ada King-Noel
And here's the dependencies: What I want you to see here is that no class or even this is used. So even if JavaScript didn't have a native object system, this demonstrates you could make your own
const Obj = (f, instance = {}) =>
(f (instance), instance)
const inherit = (o, f) =>
Object.assign (o, f (o))
const field = (o, name, value) =>
Object.assign (o, { [name]: value })
const method = (o, name, f) =>
Object.assign (o, { [name]: (...xs) => f (o, ...xs) })
Full program demonstration
// DIY class system
const Obj = (f, instance = {}) =>
(f (instance), instance)
const inherit = (o, f) =>
Object.assign (o, f (o))
const field = (o, name, value) =>
Object.assign (o, { [name]: value })
const method = (o, name, f) =>
Object.assign (o, { [name]: (...xs) => f (o, ...xs) })
// module 1
const hasFirstName = (firstName = "") => o =>
{
field (o, 'firstName', firstName)
}
// module 2
const hasMiddleName = (middleName = "") => o =>
{
field (o, 'middleName', middleName)
}
// module 3
const hasLastName = (lastName = "") => o =>
{
field (o, 'lastName', lastName)
}
// module 4
const nameable = (first, middle, last) => o =>
{
inherit (o, hasFirstName (first))
inherit (o, hasMiddleName (middle))
inherit (o, hasLastName (last))
method (o, 'getFullName', (self) => `${self.firstName} ${self.middleName} ${self.lastName}`)
method (o, 'sayHelloTo', (self, other) => `Hello ${other.getFullName ()}, my name is ${self.getFullName ()}`)
}
// Person class
const Person = (first, middle, last) =>
Obj (self => {
inherit (self, nameable (first, middle, last))
})
// demo
const p1 =
Person ('Augusta', 'Ada', 'King-Noel')
const p2 =
Person ('Gerald', 'Jay', 'Sussman')
console.log (p1.sayHelloTo (p2))
// Hello Gerald Jay Sussman, my name is Augusta Ada King-Noel
Our Person class can obviously define its own fields and methods as well
const dateDiff = (d1, d2) =>
Math.abs (d1 - d2) / 1000 / 60 / 60 / 24 / 365 >> 0
const Person = (first, middle, last, birthdate = new Date) =>
Obj (self => {
inherit (self, nameable (first, middle, last))
field (self, 'birthdate', birthdate)
method (self, 'calculateAge', (self) => dateDiff (new Date, self.birthdate))
method (self, 'sayAge', (self) => `I am ${self.calculateAge()} years old`)
})
const p2 =
Person ('Gerald', 'Jay', 'Sussman', new Date ('February 8, 1947'))
console.log (p2.sayAge ())
// I am 71 years old
Get creative and invent any other features you want
Maybe you want to make an overrideMethod that gives you the ability to define a new method with the same name, but still give the caller access to both methods
Maybe you want privateMethod or classMethod helpers
Maybe field could be enhanced to emit events when values changed
Maybe field could be changed so that values cannot be set, where mutableField could be used for fields that can change
Write it how you want it then make your wishes come true. Any limitations are you own.

Related

Why use destructuring here?

I asked this question on The Odin Project where I encountered it and was directed to research destructuring, which I did. I understand what is happening but I'm at a loss as to why it is being done this way. Simply using raw variable names with no destructuring braces gets the same result (see my jfiddle link where I removed the destructuring and got the same result). I find it hard to learn something when I'm directed to use more code, typing, and complexity to achieve the same outcome. what benefit is received here by using return {sayName} in const Person and const {sayName} = Person(name) in const Nerd? I used return sayName and const sayName in the jfiddle and got the same result.
Original code:
const Person = (name) => {
const sayName = () => console.log(`my name is ${name}`)
return {sayName}
}
const Nerd = (name) => {
// simply create a person and pull out the sayName function with destructuring assignment syntax!
const {sayName} = Person(name)
const doSomethingNerdy = () => console.log('nerd stuff')
return {sayName, doSomethingNerdy}
}
const jeff = Nerd('jeff')
jeff.sayName() //my name is jeff
jeff.doSomethingNerdy() // nerd stuff
jfiddle:
const Person = (name) => {
const sayName = () => console.log(`my name is ${name}`)
return sayName
}
const Nerd = (name) => {
// simply create a person and pull out the sayName function with destructuring assignment syntax!
const sayName = Person(name)
const doSomethingNerdy = () => console.log('nerd stuff')
return {sayName, doSomethingNerdy}
}
const jeff = Nerd('jeff')
jeff.sayName() //my name is jeff
jeff.doSomethingNerdy() // nerd stuff
The general consensus is that this is a bad example for destructuring, but I've gone too far deep and will still attempt to make sense of it.
By using destructuring, it becomes possible to add additional functions to Person.
For example, Person needs to jump:
const Person = (name) => {
const sayName = () => console.log(`my name is ${name}`)
const jump = () => console.log('I jumped') // new feature
return {sayName, jump} // jump can inserted into the object here and used externally
}
Then, as pointed out in the comments, a much better way to pass Person into Nerd would be to:
const Nerd = (name) => {
// simply create a person and pull out the sayName function with destructuring assignment syntax!
const doSomethingNerdy = () => console.log('nerd stuff')
return {...Person(name) , doSomethingNerdy}
}
Before finally, Nerd can be destructured, and all the functions inside Person and Nerd can be used.
I suppose that's what they're trying to get at.

es6 return dynamically named arrow function

If possible, what is the simplest way to return a named arrow function?
const add = a => b => b + a
const add5 => add(5)
add.name == 'add' // true
add5.name == '' // true, but I would like it to be 'add5'
So, as one can see the in example above, the returned arrow function is anonymous and I would like it to be named (ideally based on the 'parent' function and the 'parameter' a) — which is useful i.e. for debugging.
You can do this:
const add = a => (({[`add${a}`]: b => b + a})[`add${a}`]);
const add5 = add(5);
console.log(add5.name);
How it works: define a local object and assign the arrow method as a member with your desired name:
const add = a => {
const o = {
[`add${a}`]: b => b + a
};
return o[`add${a}`];
};
This isn't exactly the same, but:
const add = a => b => a + b;
const add5 = (...a) => add(5)(...a);
console.log(add5(100)); // => 105
console.log(add5.name); // => 'add5'
div{min-height:100%}
This example demonstrates how arrow function names are assigned, and this behaviour cannot be changed. Arrow function name is equal to the name of a variable or object property it was assigned to.
name is non-writable property but is configurable in most implementations, including evergreen browsers, so it's safe to use for debugging purposes:
function namedArrow(name, fn) {
Object.defineProperty(fn, 'name', { enumerable: false, value: name });
return fn;
}
const foo = namedArrow('foo!', () => { throw new Error });
foo();
It outputs:
[
For debugging purposes displayName can be used also, which is supposed to play same role and is supported by some debuggers and browser debugger tools, notably Firefox and Chrome:
function namedArrow(name, fn) {
fn.displayName = name;
return fn;
}
It results in similar output, yet it doesn't play well with Error call stack:

JavaScript - After inheriting Array the filter function becomes broken

I think I have found a bug in zombie.
This code works:
function twoArguments(a, b) { }
function threeArguments(a, b, c) { }
let pipeline = new Array();
pipeline.push(twoArguments);
pipeline.push(threeArguments);
let onlyTwoArgumentsFuncs = pipeline.filter(fn => fn.length === 2);
console.log(onlyTwoArgumentsFuncs);
But following code doesn't filter out non-two arguments functions:
class Pipeline extends Array {
constructor() {
super();
this.push(twoArguments);
this.push(threeArguments);
}
run() {
return this.filter(fn => fn.length === 2);
}
}
let pipeline = new Pipeline();
let onlyTwoArgumentsFuncs = pipeline.run();
console.log(onlyTwoArgumentsFuncs);
Still returns both of functions. Please explain why.
Setting Symbol.species to original Array constructor fixes this
class Pipeline extends Array {
static get [Symbol.species]() { return Array; }
// ...
}
EDIT:
Array.prototype.filter implementation does not mutate the original object, instead it creates a new one to store the result in. In this case, a derived constructor is used for this, which populates the object with exactly 2 values on every init.
You can set Symbol.species on the derived class to specifically tell filter to use the original Array constructor. Or you can remove initialization from the class, and use new Pipeline(twoArguments, threeArguments) or Pipeline.of(…), as #Bergi suggests.
Instead of prototyping new methods, simply variable with function say fat arrow => functions of es6 worked here
run = () => {
function twoArguments(a, b) { }
function threeArguments(a, b, c) { }
class Pipeline extends Array {
constructor() {
super();
this.push(twoArguments);
this.push(threeArguments);
}
run = () => {
return this.filter(fn => fn.length === 2);
}
}
let pipeline = new Pipeline();
let onlyTwoArgumentsFuncs = pipeline.run();
console.log(onlyTwoArgumentsFuncs);
Another possible solution is to create Array explicitly before performing filtering:
run() {
return [].concat(this).filter(fn => fn.length === 2);
}

Add multiple interface to prototype javascript [duplicate]

I've come to a point where I need to have some sort of rudimentary multiple inheritance happening in JavaScript. (I'm not here to discuss whether this is a good idea or not, so please kindly keep those comments to yourself.)
I just want to know if anyone's attempted this with any (or not) success, and how they went about it.
To boil it down, what I really need is to be able to have an object capable of inheriting a property from more than one prototype chain (i.e. each prototype could have its own proper chain), but in a given order of precedence (it will search the chains in order for the first definition).
To demonstrate how this is theoretically possible, it could be achieved by attaching the secondary chain onto the end of the primary chain, but this would affect all instances of any of those previous prototypes and that's not what I want.
Thoughts?
Multiple inheritance can be achieved in ECMAScript 6 by using Proxy objects.
Implementation
function getDesc (obj, prop) {
var desc = Object.getOwnPropertyDescriptor(obj, prop);
return desc || (obj=Object.getPrototypeOf(obj) ? getDesc(obj, prop) : void 0);
}
function multiInherit (...protos) {
return Object.create(new Proxy(Object.create(null), {
has: (target, prop) => protos.some(obj => prop in obj),
get (target, prop, receiver) {
var obj = protos.find(obj => prop in obj);
return obj ? Reflect.get(obj, prop, receiver) : void 0;
},
set (target, prop, value, receiver) {
var obj = protos.find(obj => prop in obj);
return Reflect.set(obj || Object.create(null), prop, value, receiver);
},
*enumerate (target) { yield* this.ownKeys(target); },
ownKeys(target) {
var hash = Object.create(null);
for(var obj of protos) for(var p in obj) if(!hash[p]) hash[p] = true;
return Object.getOwnPropertyNames(hash);
},
getOwnPropertyDescriptor(target, prop) {
var obj = protos.find(obj => prop in obj);
var desc = obj ? getDesc(obj, prop) : void 0;
if(desc) desc.configurable = true;
return desc;
},
preventExtensions: (target) => false,
defineProperty: (target, prop, desc) => false,
}));
}
Explanation
A proxy object consists of a target object and some traps, which define custom behavior for fundamental operations.
When creating an object which inherits from another one, we use Object.create(obj). But in this case we want multiple inheritance, so instead of obj I use a proxy that will redirect fundamental operations to the appropriate object.
I use these traps:
The has trap is a trap for the in operator. I use some to check if at least one prototype contains the property.
The get trap is a trap for getting property values. I use find to find the first prototype which contains that property, and I return the value, or call the getter on the appropriate receiver. This is handled by Reflect.get. If no prototype contains the property, I return undefined.
The set trap is a trap for setting property values. I use find to find the first prototype which contains that property, and I call its setter on the appropriate receiver. If there is no setter or no prototype contains the property, the value is defined on the appropriate receiver. This is handled by Reflect.set.
The enumerate trap is a trap for for...in loops. I iterate the enumerable properties from the first prototype, then from the second, and so on. Once a property has been iterated, I store it in a hash table to avoid iterating it again.
Warning: This trap has been removed in ES7 draft and is deprecated in browsers.
The ownKeys trap is a trap for Object.getOwnPropertyNames(). Since ES7, for...in loops keep calling [[GetPrototypeOf]] and getting the own properties of each one. So in order to make it iterate the properties of all prototypes, I use this trap to make all enumerable inherited properties appear like own properties.
The getOwnPropertyDescriptor trap is a trap for Object.getOwnPropertyDescriptor(). Making all enumerable properties appear like own properties in the ownKeys trap is not enough, for...in loops will get the descriptor to check if they are enumerable. So I use find to find the first prototype which contains that property, and I iterate its prototypical chain until I find the property owner, and I return its descriptor. If no prototype contains the property, I return undefined. The descriptor is modified to make it configurable, otherwise we could break some proxy invariants.
The preventExtensions and defineProperty traps are only included to prevent these operations from modifying the proxy target. Otherwise we could end up breaking some proxy invariants.
There are more traps available, which I don't use
The getPrototypeOf trap could be added, but there is no proper way to return the multiple prototypes. This implies instanceof won't work neither. Therefore, I let it get the prototype of the target, which initially is null.
The setPrototypeOf trap could be added and accept an array of objects, which would replace the prototypes. This is left as an exercice for the reader. Here I just let it modify the prototype of the target, which is not much useful because no trap uses the target.
The deleteProperty trap is a trap for deleting own properties. The proxy represents the inheritance, so this wouldn't make much sense. I let it attempt the deletion on the target, which should have no property anyway.
The isExtensible trap is a trap for getting the extensibility. Not much useful, given that an invariant forces it to return the same extensibility as the target. So I just let it redirect the operation to the target, which will be extensible.
The apply and construct traps are traps for calling or instantiating. They are only useful when the target is a function or a constructor.
Example
// Creating objects
var o1, o2, o3,
obj = multiInherit(o1={a:1}, o2={b:2}, o3={a:3, b:3});
// Checking property existences
'a' in obj; // true (inherited from o1)
'b' in obj; // true (inherited from o2)
'c' in obj; // false (not found)
// Setting properties
obj.c = 3;
// Reading properties
obj.a; // 1 (inherited from o1)
obj.b; // 2 (inherited from o2)
obj.c; // 3 (own property)
obj.d; // undefined (not found)
// The inheritance is "live"
obj.a; // 1 (inherited from o1)
delete o1.a;
obj.a; // 3 (inherited from o3)
// Property enumeration
for(var p in obj) p; // "c", "b", "a"
Update (2019): The original post is getting pretty outdated. This article (now internet archive link, since domain went away) and its associated GitHub library are a good modern approach.
Original post:
Multiple inheritance [edit, not proper inheritance of type, but of properties; mixins] in Javascript is pretty straightforward if you use constructed prototypes rather than generic-object ones. Here are two parent classes to inherit from:
function FoodPrototype() {
this.eat = function () {
console.log("Eating", this.name);
};
}
function Food(name) {
this.name = name;
}
Food.prototype = new FoodPrototype();
function PlantPrototype() {
this.grow = function () {
console.log("Growing", this.name);
};
}
function Plant(name) {
this.name = name;
}
Plant.prototype = new PlantPrototype();
Note that I have used the same "name" member in each case, which could be a problem if the parents did not agree about how "name" should be handled. But they're compatible (redundant, really) in this case.
Now we just need a class that inherits from both. Inheritance is done by calling the constructor function (without using the new keyword) for the prototypes and the object constructors. First, the prototype has to inherit from the parent prototypes
function FoodPlantPrototype() {
FoodPrototype.call(this);
PlantPrototype.call(this);
// plus a function of its own
this.harvest = function () {
console.log("harvest at", this.maturity);
};
}
And the constructor has to inherit from the parent constructors:
function FoodPlant(name, maturity) {
Food.call(this, name);
Plant.call(this, name);
// plus a property of its own
this.maturity = maturity;
}
FoodPlant.prototype = new FoodPlantPrototype();
Now you can grow, eat, and harvest different instances:
var fp1 = new FoodPlant('Radish', 28);
var fp2 = new FoodPlant('Corn', 90);
fp1.grow();
fp2.grow();
fp1.harvest();
fp1.eat();
fp2.harvest();
fp2.eat();
This one uses Object.create to make a real prototype chain:
function makeChain(chains) {
var c = Object.prototype;
while(chains.length) {
c = Object.create(c);
$.extend(c, chains.pop()); // some function that does mixin
}
return c;
}
For example:
var obj = makeChain([{a:1}, {a: 2, b: 3}, {c: 4}]);
will return:
a: 1
a: 2
b: 3
c: 4
<Object.prototype stuff>
so that obj.a === 1, obj.b === 3, etc.
I like John Resig's implementation of a class structure: http://ejohn.org/blog/simple-javascript-inheritance/
This can be simply extended to something like:
Class.extend = function(prop /*, prop, prop, prop */) {
for( var i=1, l=arguments.length; i<l; i++ ){
prop = $.extend( prop, arguments[i] );
}
// same code
}
which will allow you to pass in multiple objects of which to inherit. You're going to lose instanceOf capability here, but that's a given if you want multiple inheritance.
my rather convoluted example of the above is available at https://github.com/cwolves/Fetch/blob/master/support/plugins/klass/klass.js
Note that there is some dead code in that file, but it allows multiple inheritance if you want to take a look.
If you want chained inheritance (NOT multiple inheritance, but for most people it's the same thing), it can be accomplished with Class like:
var newClass = Class.extend( cls1 ).extend( cls2 ).extend( cls3 )
which will preserve the original prototype chain, but you'll also have a lot of pointless code running.
I offer a function to allow classes to be defined with multiple inheritance. It allows for code like the following:
let human = new Running({ name: 'human', numLegs: 2 });
human.run();
let airplane = new Flying({ name: 'airplane', numWings: 2 });
airplane.fly();
let dragon = new RunningFlying({ name: 'dragon', numLegs: 4, numWings: 6 });
dragon.takeFlight();
to produce output like this:
human runs with 2 legs.
airplane flies away with 2 wings!
dragon runs with 4 legs.
dragon flies away with 6 wings!
Here are what the class definitions look like:
let Named = makeClass('Named', {}, () => ({
init: function({ name }) {
this.name = name;
}
}));
let Running = makeClass('Running', { Named }, protos => ({
init: function({ name, numLegs }) {
protos.Named.init.call(this, { name });
this.numLegs = numLegs;
},
run: function() {
console.log(`${this.name} runs with ${this.numLegs} legs.`);
}
}));
let Flying = makeClass('Flying', { Named }, protos => ({
init: function({ name, numWings }) {
protos.Named.init.call(this, { name });
this.numWings = numWings;
},
fly: function( ){
console.log(`${this.name} flies away with ${this.numWings} wings!`);
}
}));
let RunningFlying = makeClass('RunningFlying', { Running, Flying }, protos => ({
init: function({ name, numLegs, numWings }) {
protos.Running.init.call(this, { name, numLegs });
protos.Flying.init.call(this, { name, numWings });
},
takeFlight: function() {
this.run();
this.fly();
}
}));
We can see that each class definition using the makeClass function accepts an Object of parent-class names mapped to parent-classes. It also accepts a function that returns an Object containing properties for the class being defined. This function has a parameter protos, which contains enough information to access any property defined by any of the parent-classes.
The final piece required is the makeClass function itself, which does quite a bit of work. Here it is, along with the rest of the code. I've commented makeClass quite heavily:
let makeClass = (name, parents={}, propertiesFn=()=>({})) => {
// The constructor just curries to a Function named "init"
let Class = function(...args) { this.init(...args); };
// This allows instances to be named properly in the terminal
Object.defineProperty(Class, 'name', { value: name });
// Tracking parents of `Class` allows for inheritance queries later
Class.parents = parents;
// Initialize prototype
Class.prototype = Object.create(null);
// Collect all parent-class prototypes. `Object.getOwnPropertyNames`
// will get us the best results. Finally, we'll be able to reference
// a property like "usefulMethod" of Class "ParentClass3" with:
// `parProtos.ParentClass3.usefulMethod`
let parProtos = {};
for (let parName in parents) {
let proto = parents[parName].prototype;
parProtos[parName] = {};
for (let k of Object.getOwnPropertyNames(proto)) {
parProtos[parName][k] = proto[k];
}
}
// Resolve `properties` as the result of calling `propertiesFn`. Pass
// `parProtos`, so a child-class can access parent-class methods, and
// pass `Class` so methods of the child-class have a reference to it
let properties = propertiesFn(parProtos, Class);
properties.constructor = Class; // Ensure "constructor" prop exists
// If two parent-classes define a property under the same name, we
// have a "collision". In cases of collisions, the child-class *must*
// define a method (and within that method it can decide how to call
// the parent-class methods of the same name). For every named
// property of every parent-class, we'll track a `Set` containing all
// the methods that fall under that name. Any `Set` of size greater
// than one indicates a collision.
let propsByName = {}; // Will map property names to `Set`s
for (let parName in parProtos) {
for (let propName in parProtos[parName]) {
// Now track the property `parProtos[parName][propName]` under the
// label of `propName`
if (!propsByName.hasOwnProperty(propName))
propsByName[propName] = new Set();
propsByName[propName].add(parProtos[parName][propName]);
}
}
// For all methods defined by the child-class, create or replace the
// entry in `propsByName` with a Set containing a single item; the
// child-class' property at that property name (this also guarantees
// there is no collision at this property name). Note property names
// prefixed with "$" will be considered class properties (and the "$"
// will be removed).
for (let propName in properties) {
if (propName[0] === '$') {
// The "$" indicates a class property; attach to `Class`:
Class[propName.slice(1)] = properties[propName];
} else {
// No "$" indicates an instance property; attach to `propsByName`:
propsByName[propName] = new Set([ properties[propName] ]);
}
}
// Ensure that "init" is defined by a parent-class or by the child:
if (!propsByName.hasOwnProperty('init'))
throw Error(`Class "${name}" is missing an "init" method`);
// For each property name in `propsByName`, ensure that there is no
// collision at that property name, and if there isn't, attach it to
// the prototype! `Object.defineProperty` can ensure that prototype
// properties won't appear during iteration with `in` keyword:
for (let propName in propsByName) {
let propsAtName = propsByName[propName];
if (propsAtName.size > 1)
throw new Error(`Class "${name}" has conflict at "${propName}"`);
Object.defineProperty(Class.prototype, propName, {
enumerable: false,
writable: true,
value: propsAtName.values().next().value // Get 1st item in Set
});
}
return Class;
};
let Named = makeClass('Named', {}, () => ({
init: function({ name }) {
this.name = name;
}
}));
let Running = makeClass('Running', { Named }, protos => ({
init: function({ name, numLegs }) {
protos.Named.init.call(this, { name });
this.numLegs = numLegs;
},
run: function() {
console.log(`${this.name} runs with ${this.numLegs} legs.`);
}
}));
let Flying = makeClass('Flying', { Named }, protos => ({
init: function({ name, numWings }) {
protos.Named.init.call(this, { name });
this.numWings = numWings;
},
fly: function( ){
console.log(`${this.name} flies away with ${this.numWings} wings!`);
}
}));
let RunningFlying = makeClass('RunningFlying', { Running, Flying }, protos => ({
init: function({ name, numLegs, numWings }) {
protos.Running.init.call(this, { name, numLegs });
protos.Flying.init.call(this, { name, numWings });
},
takeFlight: function() {
this.run();
this.fly();
}
}));
let human = new Running({ name: 'human', numLegs: 2 });
human.run();
let airplane = new Flying({ name: 'airplane', numWings: 2 });
airplane.fly();
let dragon = new RunningFlying({ name: 'dragon', numLegs: 4, numWings: 6 });
dragon.takeFlight();
The makeClass function also supports class properties; these are defined by prefixing property names with the $ symbol (note that the final property name that results will have the $ removed). With this in mind, we could write a specialized Dragon class that models the "type" of the Dragon, where the list of available Dragon types is stored on the Class itself, as opposed to on the instances:
let Dragon = makeClass('Dragon', { RunningFlying }, protos => ({
$types: {
wyvern: 'wyvern',
drake: 'drake',
hydra: 'hydra'
},
init: function({ name, numLegs, numWings, type }) {
protos.RunningFlying.init.call(this, { name, numLegs, numWings });
this.type = type;
},
description: function() {
return `A ${this.type}-type dragon with ${this.numLegs} legs and ${this.numWings} wings`;
}
}));
let dragon1 = new Dragon({ name: 'dragon1', numLegs: 2, numWings: 4, type: Dragon.types.drake });
let dragon2 = new Dragon({ name: 'dragon2', numLegs: 4, numWings: 2, type: Dragon.types.hydra });
The Challenges of Multiple Inheritance
Anyone who followed the code for makeClass closely will note a rather significant undesirable phenomenon occurring silently when the above code runs: instantiating a RunningFlying will result in TWO calls to the Named constructor!
This is because the inheritance graph looks like this:
(^^ More Specialized ^^)
RunningFlying
/ \
/ \
Running Flying
\ /
\ /
Named
(vv More Abstract vv)
When there are multiple paths to the same parent-class in a sub-class' inheritance graph, instantiations of the sub-class will invoke that parent-class' constructor multiple times.
Combatting this is non-trivial. Let's look at some examples with simplified classnames. We'll consider class A, the most abstract parent-class, classes B and C, which both inherit from A, and class BC which inherits from B and C (and hence conceptually "double-inherits" from A):
let A = makeClass('A', {}, () => ({
init: function() {
console.log('Construct A');
}
}));
let B = makeClass('B', { A }, protos => ({
init: function() {
protos.A.init.call(this);
console.log('Construct B');
}
}));
let C = makeClass('C', { A }, protos => ({
init: function() {
protos.A.init.call(this);
console.log('Construct C');
}
}));
let BC = makeClass('BC', { B, C }, protos => ({
init: function() {
// Overall "Construct A" is logged twice:
protos.B.init.call(this); // -> console.log('Construct A'); console.log('Construct B');
protos.C.init.call(this); // -> console.log('Construct A'); console.log('Construct C');
console.log('Construct BC');
}
}));
If we want to prevent BC from double-invoking A.prototype.init we may need to abandon the style of directly calling inherited constructors. We will need some level of indirection to check whether duplicate calls are occurring, and short-circuit before they happen.
We could consider changing the parameters supplied to the properties function: alongside protos, an Object containing raw data describing inherited properties, we could also include a utility function for calling an instance method in such a way that parent methods are also called, but duplicate calls are detected and prevented. Let's take a look at where we establish the parameters for the propertiesFn Function:
let makeClass = (name, parents, propertiesFn) => {
/* ... a bunch of makeClass logic ... */
// Allows referencing inherited functions; e.g. `parProtos.ParentClass3.usefulMethod`
let parProtos = {};
/* ... collect all parent methods in `parProtos` ... */
// Utility functions for calling inherited methods:
let util = {};
util.invokeNoDuplicates = (instance, fnName, args, dups=new Set()) => {
// Invoke every parent method of name `fnName` first...
for (let parName of parProtos) {
if (parProtos[parName].hasOwnProperty(fnName)) {
// Our parent named `parName` defines the function named `fnName`
let fn = parProtos[parName][fnName];
// Check if this function has already been encountered.
// This solves our duplicate-invocation problem!!
if (dups.has(fn)) continue;
dups.add(fn);
// This is the first time this Function has been encountered.
// Call it on `instance`, with the desired args. Make sure we
// include `dups`, so that if the parent method invokes further
// inherited methods we don't lose track of what functions have
// have already been called.
fn.call(instance, ...args, dups);
}
}
};
// Now we can call `propertiesFn` with an additional `util` param:
// Resolve `properties` as the result of calling `propertiesFn`:
let properties = propertiesFn(parProtos, util, Class);
/* ... a bunch more makeClass logic ... */
};
The whole purpose of the above change to makeClass is so that we have an additional argument supplied to our propertiesFn when we invoke makeClass. We should also be aware that every function defined in any class may now receive a parameter after all its others, named dup, which is a Set that holds all functions that have already been called as a result of calling the inherited method:
let A = makeClass('A', {}, () => ({
init: function() {
console.log('Construct A');
}
}));
let B = makeClass('B', { A }, (protos, util) => ({
init: function(dups) {
util.invokeNoDuplicates(this, 'init', [ /* no args */ ], dups);
console.log('Construct B');
}
}));
let C = makeClass('C', { A }, (protos, util) => ({
init: function(dups) {
util.invokeNoDuplicates(this, 'init', [ /* no args */ ], dups);
console.log('Construct C');
}
}));
let BC = makeClass('BC', { B, C }, (protos, util) => ({
init: function(dups) {
util.invokeNoDuplicates(this, 'init', [ /* no args */ ], dups);
console.log('Construct BC');
}
}));
This new style actually succeeds in ensuring "Construct A" is only logged once when an instance of BC is initialized. But there are three downsides, the third of which is very critical:
This code has become less readable and maintainable. A lot of complexity hides behind the util.invokeNoDuplicates function, and thinking about how this style avoids multi-invocation is non-intuitive and headache inducing. We also have that pesky dups parameter, which really needs to be defined on every single function in the class. Ouch.
This code is slower - quite a bit more indirection and computation is required to achieve desirable results with multiple inheritance. Unfortunately this is likely to be the case with any solution to our multiple-invocation problem.
Most significantly, the structure of functions which rely on inheritance has become very rigid. If a sub-class NiftyClass overrides a function niftyFunction, and uses util.invokeNoDuplicates(this, 'niftyFunction', ...) to run it without duplicate-invocation, NiftyClass.prototype.niftyFunction will call the function named niftyFunction of every parent class that defines it, ignore any return values from those classes, and finally perform the specialized logic of NiftyClass.prototype.niftyFunction. This is the only possible structure. If NiftyClass inherits CoolClass and GoodClass, and both these parent-classes provide niftyFunction definitions of their own, NiftyClass.prototype.niftyFunction will never (without risking multiple-invocation) be able to:
A. Run the specialized logic of NiftyClass first, then the specialized logic of parent-classes
B. Run the specialized logic of NiftyClass at any point other than after all specialized parent logic has completed
C. Behave conditionally depending on the return values of its parent's specialized logic
D. Avoid running a particular parent's specialized niftyFunction altogether
Of course, we could solve each lettered problem above by defining specialized functions under util:
A. define util.invokeNoDuplicatesSubClassLogicFirst(instance, fnName, ...)
B. define util.invokeNoDuplicatesSubClassAfterParent(parentName, instance, fnName, ...) (Where parentName is the name of the parent whose specialized logic will be immediately followed by the child-classes' specialized logic)
C. define util.invokeNoDuplicatesCanShortCircuitOnParent(parentName, testFn, instance, fnName, ...) (In this case testFn would receive the result of the specialized logic for the parent named parentName, and would return a true/false value indicating whether the short-circuit should happen)
D. define util.invokeNoDuplicatesBlackListedParents(blackList, instance, fnName, ...) (In this case blackList would be an Array of parent names whose specialized logic should be skipped altogether)
These solutions are all available, but this is total mayhem! For every unique structure that an inherited function call can take, we would need a specialized method defined under util. What an absolute disaster.
With this in mind we can start to see the challenges of implementing good multiple inheritance. The full implementation of makeClass I provided in this answer does not even consider the multiple-invocation problem, or many other problems which arise regarding multiple inheritance.
This answer is getting very long. I hope the makeClass implementation I included is still useful, even if it isn't perfect. I also hope anyone interested in this topic has gained more context to keep in mind as they do further reading!
Don't get confused with JavaScript framework implementations of multiple inheritance.
All you need to do is use Object.create() to create a new object each time with the specified prototype object and properties, then be sure to change the Object.prototype.constructor each step of the way if you plan on instantiating B in the future.
To inherit instance properties thisA and thisB we use Function.prototype.call() at the end of each object function. This is optional if you only care about inheriting the prototype.
Run the following code somewhere and observe objC:
function A() {
this.thisA = 4; // objC will contain this property
}
A.prototype.a = 2; // objC will contain this property
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
function B() {
this.thisB = 55; // objC will contain this property
A.call(this);
}
B.prototype.b = 3; // objC will contain this property
C.prototype = Object.create(B.prototype);
C.prototype.constructor = C;
function C() {
this.thisC = 123; // objC will contain this property
B.call(this);
}
C.prototype.c = 2; // objC will contain this property
var objC = new C();
B inherits the prototype from A
C inherits the prototype from B
objC is an instance of C
This is a good explanation of the steps above:
OOP In JavaScript: What You NEED to Know
I’m in no way an expert on javascript OOP, but if I understand you correctly you want something like (pseudo-code):
Earth.shape = 'round';
Animal.shape = 'random';
Cat inherit from (Earth, Animal);
Cat.shape = 'random' or 'round' depending on inheritance order;
In that case, I’d try something like:
var Earth = function(){};
Earth.prototype.shape = 'round';
var Animal = function(){};
Animal.prototype.shape = 'random';
Animal.prototype.head = true;
var Cat = function(){};
MultiInherit(Cat, Earth, Animal);
console.log(new Cat().shape); // yields "round", since I reversed the inheritance order
console.log(new Cat().head); // true
function MultiInherit() {
var c = [].shift.call(arguments),
len = arguments.length
while(len--) {
$.extend(c.prototype, new arguments[len]());
}
}
It's possible to implement multiple inheritance in JavaScript, although very few libraries does it.
I could point Ring.js, the only example I know.
I was working on this a lot today and trying to achieve this myself in ES6. The way I did it was using Browserify, Babel and then I tested it with Wallaby and it seemed to work. My goal is to extend the current Array, include ES6, ES7 and add some additional custom features I need in the prototype for dealing with audio data.
Wallaby passes 4 of my tests. The example.js file can be pasted in the console and you can see that the 'includes' property is in the prototype of the class. I still want to test this more tomorrow.
Here's my method: (I will most likely refactor and repackage as a module after some sleep!)
var includes = require('./polyfills/includes');
var keys = Object.getOwnPropertyNames(includes.prototype);
keys.shift();
class ArrayIncludesPollyfills extends Array {}
function inherit (...keys) {
keys.map(function(key){
ArrayIncludesPollyfills.prototype[key]= includes.prototype[key];
});
}
inherit(keys);
module.exports = ArrayIncludesPollyfills
Github Repo:
https://github.com/danieldram/array-includes-polyfill
I think it is ridiculously simple. The issue here is that the child class will only refer to instanceof for the first class you call
https://jsfiddle.net/1033xzyt/19/
function Foo() {
this.bar = 'bar';
return this;
}
Foo.prototype.test = function(){return 1;}
function Bar() {
this.bro = 'bro';
return this;
}
Bar.prototype.test2 = function(){return 2;}
function Cool() {
Foo.call(this);
Bar.call(this);
return this;
}
var combine = Object.create(Foo.prototype);
$.extend(combine, Object.create(Bar.prototype));
Cool.prototype = Object.create(combine);
Cool.prototype.constructor = Cool;
var cool = new Cool();
console.log(cool.test()); // 1
console.log(cool.test2()); //2
console.log(cool.bro) //bro
console.log(cool.bar) //bar
console.log(cool instanceof Foo); //true
console.log(cool instanceof Bar); //false
Check the code below which IS showing support for multiple inheritance. Done by using PROTOTYPAL INHERITANCE
function A(name) {
this.name = name;
}
A.prototype.setName = function (name) {
this.name = name;
}
function B(age) {
this.age = age;
}
B.prototype.setAge = function (age) {
this.age = age;
}
function AB(name, age) {
A.prototype.setName.call(this, name);
B.prototype.setAge.call(this, age);
}
AB.prototype = Object.assign({}, Object.create(A.prototype), Object.create(B.prototype));
AB.prototype.toString = function () {
return `Name: ${this.name} has age: ${this.age}`
}
const a = new A("shivang");
const b = new B(32);
console.log(a.name);
console.log(b.age);
const ab = new AB("indu", 27);
console.log(ab.toString());
Take a look of the package IeUnit.
The concept assimilation implemented in IeUnit seems to offers what you are looking for in a quite dynamical way.
Here is an example of prototype chaining using constructor functions:
function Lifeform () { // 1st Constructor function
this.isLifeform = true;
}
function Animal () { // 2nd Constructor function
this.isAnimal = true;
}
Animal.prototype = new Lifeform(); // Animal is a lifeform
function Mammal () { // 3rd Constructor function
this.isMammal = true;
}
Mammal.prototype = new Animal(); // Mammal is an animal
function Cat (species) { // 4th Constructor function
this.isCat = true;
this.species = species
}
Cat.prototype = new Mammal(); // Cat is a mammal
This concept uses Yehuda Katz's definition of a "class" for JavaScript:
...a JavaScript "class" is just a Function object that serves as a constructor plus an attached prototype object. (Source: Guru Katz)
Unlike the Object.create approach, when the classes are built in this way and we want to create instances of a "class", we don't need to know what each "class" is inheriting from. We just use new.
// Make an instance object of the Cat "Class"
var tiger = new Cat("tiger");
console.log(tiger.isCat, tiger.isMammal, tiger.isAnimal, tiger.isLifeform);
// Outputs: true true true true
The order of precendence should make sense. First it looks in the instance object, then it's prototype, then the next prototype, etc.
// Let's say we have another instance, a special alien cat
var alienCat = new Cat("alien");
// We can define a property for the instance object and that will take
// precendence over the value in the Mammal class (down the chain)
alienCat.isMammal = false;
// OR maybe all cats are mutated to be non-mammals
Cat.prototype.isMammal = false;
console.log(alienCat);
We can also modify the prototypes which will effect all objects built on the class.
// All cats are mutated to be non-mammals
Cat.prototype.isMammal = false;
console.log(tiger, alienCat);
I originally wrote some of this up with this answer.
A latecomer in the scene is SimpleDeclare. However, when dealing with multiple inheritance, you will still end up with copies of the original constructors. That's a necessity in Javascript...
Merc.
I would use ds.oop. Its similar to prototype.js and others. makes multiple inheritance very easy and its minimalist. (only 2 or 3 kb) Also supports some other neat features like interfaces and dependency injection
/*** multiple inheritance example ***********************************/
var Runner = ds.class({
run: function() { console.log('I am running...'); }
});
var Walker = ds.class({
walk: function() { console.log('I am walking...'); }
});
var Person = ds.class({
inherits: [Runner, Walker],
eat: function() { console.log('I am eating...'); }
});
var person = new Person();
person.run();
person.walk();
person.eat();
How about this, it implements multiple inheritance in JavaScript:
class Car {
constructor(brand) {
this.carname = brand;
}
show() {
return 'I have a ' + this.carname;
}
}
class Asset {
constructor(price) {
this.price = price;
}
show() {
return 'its estimated price is ' + this.price;
}
}
class Model_i1 { // extends Car and Asset (just a comment for ourselves)
//
constructor(brand, price, usefulness) {
specialize_with(this, new Car(brand));
specialize_with(this, new Asset(price));
this.usefulness = usefulness;
}
show() {
return Car.prototype.show.call(this) + ", " + Asset.prototype.show.call(this) + ", Model_i1";
}
}
mycar = new Model_i1("Ford Mustang", "$100K", 16);
document.getElementById("demo").innerHTML = mycar.show();
And here's the code for specialize_with() utility function:
function specialize_with(o, S) { for (var prop in S) { o[prop] = S[prop]; } }
This is real code that runs. You can copy-paste it in html file, and try it yourself. It does work.
That's the effort to implement MI in JavaScript. Not much of code, more of a know-how.
Please feel free to look at my complete article on this, https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS
I just used to assign what classes I need in properties of others, and add a proxy to auto-point to them i like:
class A {
constructor()
{
this.test = "a test";
}
method()
{
console.log("in the method");
}
}
class B {
constructor()
{
this.extends = [new A()];
return new Proxy(this, {
get: function(obj, prop) {
if(prop in obj)
return obj[prop];
let response = obj.extends.find(function (extended) {
if(prop in extended)
return extended[prop];
});
return response ? response[prop] : Reflect.get(...arguments);
},
})
}
}
let b = new B();
b.test ;// "a test";
b.method(); // in the method

ES6: call class constructor without new keyword

Given a simple class
class Foo {
constructor(x) {
if (!(this instanceof Foo)) return new Foo(x);
this.x = x;
}
hello() {
return `hello ${this.x}`;
}
}
Is it possible to call the class constructor without the new keyword?
Usage should allow
(new Foo("world")).hello(); // "hello world"
Or
Foo("world").hello(); // "hello world"
But the latter fails with
Cannot call a class as a function
Classes have a "class body" that is a constructor.
If you use an internal constructor() function, that function would be the same class body as well, and would be what is called when the class is called, hence a class is always a constructor.
Constructors require the use of the new operator to create a new instance, as such invoking a class without the new operator results in an error, as it's required for the class constructor to create a new instance.
The error message is also quite specific, and correct
TypeError: Class constructors cannot be invoked without 'new'
You could:
either use a regular function instead of a class1.
Always call the class with new.
Call the class inside a wrapping regular function, always using new, that way you get the benefits of classes, but the wrapping function can still be called with and without the new operator2.
1)
function Foo(x) {
if (!(this instanceof Foo)) return new Foo(x);
this.x = x;
this.hello = function() {
return this.x;
}
}
2)
class Foo {
constructor(x) {
this.x = x;
}
hello() {
return `hello ${this.x}`;
}
}
var _old = Foo;
Foo = function(...args) { return new _old(...args) };
As others have pointed out, ES2015 spec strictly states that such call should throw TypeError, but at the same time, it provides feature that can be used to achieve exactly the desired result, namely Proxies.
Proxies allows us to virtualize over a concept of an object. For instance, they can be used to change some behaviour of particular object without affecting anything else.
In your specific use case, class Foo is Function object which can be called -- this normally means that body of this function will be executed. But this can be changed with Proxy:
const _Foo = new Proxy(Foo, {
// target = Foo
apply (target, thisArg, argumentsList) {
return new target(...argumentsList);
}
});
_Foo("world").hello();
const f = _Foo("world");
f instanceof Foo; // true
f instanceof _Foo; // true
(Note that _Foo is now the class you want to expose, so identifiers should probably be the other way round)
If run by browsers that support Proxies, calling _Foo(...) will now execute apply trap function instead of the original constructor.
At the same time, this "new" _Foo class is indistinguishable from original Foo (apart from being able to call it as a normal function). Similarly, there is no difference by which you can tell object created with Foo and _Foo.
The biggest downside of this is that it cannot be transpiled or polyfilled, but still it's viable solution for having Scala-like class applied in JS in the future.
Here's a pattern I've come across that really helps me. It doesn't use a class, but it doesn't require the use of new either. Win/Win.
const Foo = x => ({
x,
hello: () => `hello ${x}`,
increment: () => Foo(x + 1),
add: ({x: y}) => Foo(x + y)
})
console.log(Foo(1).x) // 1
console.log(Foo(1).hello()) // hello 1
console.log(Foo(1).increment().hello()) // hello 2
console.log(Foo(1).add(Foo(2)).hello()) // hello 3
i just made this npm module for you ;)
https://www.npmjs.com/package/classy-decorator
import classy from "classy-decorator";
#classy()
class IamClassy {
constructor() {
console.log("IamClassy Instance!");
}
}
console.log(new IamClassy() instanceof IamClassy()); // true
console.log(IamClassy() instanceof IamClassy()); // true
No, this is not possible. Constructors that are created using the class keyword can only be constructed with new, if they are [[call]]ed without they always throw a TypeError1 (and there's not even a way to detect this from the outside).
1: I'm not sure whether transpilers get this right
You can use a normal function as a workaround, though:
class Foo {
constructor(x) {
this.x = x;
}
hello() {
return `hello ${this.x}`;
}
}
{
const _Foo = Foo;
Foo = function(...args) {
return new _Foo(...args);
};
Foo.prototype = _Foo.prototype;
}
Disclaimer: instanceof and extending Foo.prototype work as normal, Foo.length does not, .constructor and static methods do not but can be fixed by adding Foo.prototype.constructor = Foo; and Object.setPrototypeOf(Foo, _Foo) if required.
For subclassing Foo (not _Foo) with class Bar extends Foo …, you should use return Reflect.construct(_Foo, args, new.target) instead of the new _Foo call. Subclassing in ES5 style (with Foo.call(this, …)) is not possible.
class MyClass {
constructor(param) {
// ...
}
static create(param) {
return new MyClass(param);
}
doSomething() {
// ...
}
}
MyClass.create('Hello World').doSomething();
Is that what you want?
If you need some logic when creating a new instance of MyClass, it could be helpful to implement a "CreationStrategy", to outsorce the logic (for example complex builder logic with validation)
Edit: As discussed in the comments It does not make sense to create some sort of Builder Pattern with a separate class in JavaScript. Removed related example.
Here's a where you can use a 'scope safe constructor'
Observe this code:
function Student(name) {
if(this instanceof Student) {
this.name = name;
} else {
return new Student(name);
}
}
Now you can create a Student object without using new as follows:
var stud1 = Student('Kia');
Dug up this one in the draft
Constructors defined using class definition syntax throw when called as functions
So I guess that's not possible with classes.
Call class constructor manually can be usefull when refactoring code (having parts of the code in ES6, other parts beeing function & prototype definition)
I ended up with a small, yet usefull boilerplate, slicing the constructor into another function. Period.
class Foo {
constructor() {
//as i will not be able to call the constructor, just move everything to initialize
this.initialize.apply(this, arguments)
}
initialize() {
this.stuff = {};
//whatever you want
}
}
function Bar () {
Foo.prototype.initialize.call(this);
}
Bar.prototype.stuff = function() {}
I had problems extending classes converted with the transformation function mentioned in some other answers. The issue seems to be that node (as of v9.4.0) doesn't properly support the argument spread operator ((...args) =>).
This function based on the transpiled output of the classy-decorator (mentioned in another answer) works for me and doesn't require support for decorators or the argument spread operator.
// function that calls `new` for you on class constructors, simply call
// YourClass = bindNew(YourClass)
function bindNew(Class) {
function _Class() {
for (
var len = arguments.length, rest = Array(len), key = 0;
key < len;
key++
) {
rest[key] = arguments[key];
}
return new (Function.prototype.bind.apply(Class, [null].concat(rest)))();
}
_Class.prototype = Class.prototype;
return _Class;
}
Usage:
class X {}
X = bindNew(X);
// or
const Y = bindNew(class Y {});
const x = new X();
const x2 = X(); // woohoo
x instanceof X; // true
x2 instanceof X; // true
class Z extends X {} // works too
As a bonus, TypeScript (with "es5" output) seems to be fine with the old instanceof trick (well, it won't typecheck if used without new but it works anyhow):
class X {
constructor() {
if (!(this instanceof X)) {
return new X();
}
}
}
because it compiles it down to:
var X = /** #class */ (function () {
function X() {
if (!(this instanceof X)) {
return new X();
}
}
return X;
}());
Alright I have another answer here, and I think this one is pretty innovative.
Basically, the problem with doing something similar to Naomik's answer is that you create functions each and every time you chain methods together.
EDIT: This solution shares the same problem, however, this answer is being left up for educational purposes.
So here I'm offering a way to merely bind new values to your methods--which are basically just independent functions. This offer the additional benefit of being able to import functions from different modules into the newly constructed object.
Okay, so here it goes.
const assoc = (prop, value, obj) =>
Object.assign({},obj,{[prop]: value})
const reducer = ( $values, accumulate, [key,val] ) => assoc( key, val.bind( undefined,...$values ), accumulate )
const bindValuesToMethods = ( $methods, ...$values ) =>
Object.entries( $methods ).reduce( reducer.bind( undefined, ...$values), {} )
const prepareInstance = (instanceMethods, staticMethods = ({}) ) => Object.assign(
bindValuesToMethods.bind( undefined, instanceMethods ),
staticMethods
)
// Let's make our class-like function
const RightInstanceMethods = ({
chain: (x,f) => f(x),
map: (x,f) => Right(f(x)),
fold: (x,l,r) => r(x),
inspect: (x) => `Right(${x})`
})
const RightStaticMethods = ({
of: x => Right(x)
})
const Right = prepareInstance(RightInstanceMethods,RightStaticMethods)
Now you can do
Right(4)
.map(x=>x+1)
.map(x=>x*2)
.inspect()
You can also do
Right.of(4)
.map(x=>x+1)
.map(x=>x*2)
.inspect()
You also have the added benefit of being able to export from modules as such
export const Right = prepareInstance(RightInstanceMethods,RightStaticMethods)
While you don't get ClassInstance.constructor you do have FunctorInstance.name (note, you may need to polyfill Function.name and/or not use an arrow function for export for browser compatibility with Function.name purposes)
export function Right(...args){
return prepareInstance(RightInstanceMethods,RightStaticMethods)(...args)
}
PS - New name suggestions for prepareInstance welcomed, see Gist.
https://gist.github.com/babakness/56da19ba85e0eaa43ae5577bc0064456
As pointed out by you and others
Foo("world").hello();
fails with an error because it is an error,
according to rules of ES6 syntax.
Others pointed out that
(new Foo("world")).hello();
works but is clunky because
It needs the 'new' AND
It needs the extra parenthesis.
I agree it is clunky. So I'm often using
this solution instead:
In your class Foo, create a static method
named 'new':
static new (...args)
{ return new this (...args);
}
Use it like this:
Foo.new("world").hello();
This way I hide the "clunkiness" inside
this static method 'new()'.
Note that this method new() is generic,
it will work as is also
when inherited to sub-classes. If you need
to customize it in a subclass you can first call:
super.new(...args)
and then add any other stuff you need in the
method in a subclass, before returning its result.
A recapped working "one-line" solution for ES6: explained
The answer posted above by Bergi is basically correct.
TLDR; skip to the end 😎 for the one-liner solution
Bergi's answer may seem a unclear when reading it. So, here is a more expanded code-sample that illustrates TWO new ES6 features to achieve the desired goals.
Together, they let a single function C (below) provide the dual-role of a factory and new-able fn; which constructs a B inst that derives from a A.
The B constructor utilizes super handling to invoke the A constructor with initialization arguments. In our final #3 - #4 examples constructed by C.
The A constructor demonstrates the semantics of the new.target psuedo-var to discover new was actually invoked with B.
First, we will make use of ES6 new.target psuedo-var that gives us the RHS of a new RHS() expression.
Technically, we could have gotten new.target as this?.__proto__?.constructor; they are equivalent.
Second, we will make use of ES6 Reflect.construct. Which is crucial to working around the ES6 class constructor invocation constraints; if we are bound and determined to not use new RHS(...).
Test the following and see for yourself its output (also provided in #1-4 below).
class A {
constructor(...a) {
const descendentType = new.target;
console.log(`A's constructor seeing 'new' invoked on ${descendentType?.name} with args: %o`,a);
}
}
class B extends A {
constructor(...a) {
super(...a);
}
}
// C is our DUAL mode Factory
function C(...a) {
console.log(`C's new.target => ${new.target?.name}`);
const inst = new.target ? Reflect.construct(B, a) : new B(...a);
console.log(`C has constructed a ${inst.__proto__.constructor.name} inst`);
return inst;
}
Which we can then invoke it in the following ways:
new A('NEW-A()')
output => "A's constructor seeing 'new' invoked on A with args: ['NEW-A()']"
new B('NEW-B()')
output => "A's constructor seeing 'new' invoked on B with args: ['NEW-B()']"
new C('NEW-C()')
output => "C's new.target => C"
output => "A's constructor seeing 'new' invoked on B with args: ['NEW-C()']"
output => "C has constructed a B inst"
C('PLAIN-C()')
output => "C's new.target => undefined"
output => "A's constructor seeing 'new' invoked on B with args: ['PLAIN-C()']"
output => "C has constructed a B inst"
Where #3 and #4 achieve the originally desired goals.
The simplified `C` looks like:
function C(...a) {return Reflect.construct(B, a);}
OR - if 3rd arg of Reflect.construct not utilized for init.
function C(...a) {return new B(...a);}
Beware: C must be a function not a class for this to both be allowed, and to work returning an alternate this on a new C() invocation, etc.
Also to circumvent strict mode rules for arguments.callee requires using a closure (smalltalk-block. Illustrated below:
class B extends A {
// embedding within a class and generically referencing it requires =>
static C = (() => {
const $class = this; return function(...a) {
return Reflect.construct($class, a);}})();
// Read more on `Reflect.construct` 3rd argument to see more capabilities
// for why it does MORE than just `new $class(...a)` would do.
}
exports.C = B.C;
⛐⚠️⛐ You could do some awful things like fiddle the __proto__ on the resulting inst and change out its constructor and name. Which would make it look and feel like a real subclass C of B depending on how far you want to go to manipulate the object-model. The subtleties abound in what happens with getters/setters, super and # privates. But for much of that you can STAY ES6 CLEAN and get clever with using extends and providing a template superclass flattened mixin tree; which I do a lot of in efekt for supporting tiny-but-complete µhtml reactive custom-elements parts and related PWA app models and responsive dynamic just-in-time versioned code bundling from EdgeS ESS backend servers. As in ... const M = $class => class extends $class {...}.
My motivations...
I posted this to help explain the semantics and a working ES6 solution, which is what I use to support subclassing Promise to provide FutureValue with better workflow handling capabilities in my github efekt library (EdgeS Front End Kit library).
In 2022, with ES6 onwards you can do it with the static method that can be called before the instance of the class is created, to create a instance of the class.
So the code should look something like this:
class Foo {
constructor(x) {
this.x = x;
}
//static class
static Init(x) {
return new Foo(x)
}
sayHello() {
return `hello ${this.x}`;
}
}
//so if i call
Foo.Init('world').sayHello();
//it prints: hello world
But if you are doing all this to make a chain of method you can also look at the following construct:
function MyName(name) {
if (this instanceof MyName) {
this.name = name,
this.prepend = function(n) {
this.name = `${n} ${this.name}`;
return this;
}
,
this.append = function(n) {
this.name = `${this.name} ${n} `;
return this;
}
,
this.show = function() {
return this.name;
}
} else {
return new MyName(name);
}
}
//Call
MyName('vinod').prepend('dev').append('hacks').show();
//prints: dev vinod hacks
The method above returns this at the end of each method which makes the object, properties & method avaialble.
The good part is these methods can be used again & again to create a sentence as
MyName('vinod').prepend('dev').append('hacks')
.prepend("the").append('javascript').append('for Stackoverflow').show();
I have used it as a stringBuilder or to generate xml dynamically.
Calling the class constructor without the new keyword is not possible.
The error message is quite specific.
See a blog post on 2ality and the spec:
However, you can only invoke a class via new, not via a function call (Sect. 9.2.2 in the spec):
> Point()
TypeError: Classes can’t be function-called
I'm adding this as a follow up to a comment by naomik and utilizing on the method illustrated by Tim and Bergi. I'm also going to suggest an of function to use as a general case.
To do this in a functional way AND utilize the efficiency of prototypes (not re-create all method each time a new instance is created), one could use this pattern
const Foo = function(x){ this._value = x ... }
Foo.of = function(x){ return new Foo(x) }
Foo.prototype = {
increment(){ return Foo.of(this._value + 1) },
...
}
Please note that this is consistent with fantasy-land JS specs
https://github.com/fantasyland/fantasy-land#of-method
I personally feel that it is cleaner to use the ES6 class syntax
class Foo {
static of(x) { new Foo(x)}
constructor(x) { this._value = x }
increment() { Foo.of(this._value+1) }
}
Now one could wrap this in a closure as such
class Foo {
static of(x) { new _Foo(x)}
constructor(x) { this._value = x }
increment() { Foo.of(this._value+1) }
}
function FooOf (x) {
return Foo.of(x)
}
Or rename FooOf and Foo as desired, ie the class could be FooClass and the function just Foo, etc.
This is better than place the class in the function because creating new instances doesn't burden us with creating new classes as well.
Yet another way is to create a an of function
const of = (classObj,...args) => (
classObj.of
? classObj.of(value)
: new classObj(args)
)
And then do something like of(Foo,5).increment()
Still finding interesting ways to use instanceof without relying on new or class keywords. In this example program, we compute the 100,000th fibonacci number in less than one second. The result is over 20,000 digits long -
const fib = x =>
Loop // <- no `new`
( (n, a, b) =>
n <= 0n
? String(a) // <- no `new`
: Recur(n - 1n, b, a + b) // <- no `new`
, BigInt(x) // <- no `new`
, 0n
, 1n
)
function Loop (f, ...init)
{ let r = f(...init)
while (r instanceof Recur) // <- instanceof works
r = f(...r)
return r
}
function Recur (...v)
{ return Object.create // <- not a class, but works
( Recur.prototype // <- set prototype
, { constructor: { value: Recur } // <- set constructor
, [Symbol.iterator]: { value: _ => v.values() } // <- whatever you want
}
)
}
document.body.textContent = fib(100000)
body { overflow-wrap: anywhere; }
I don't know why I haven't thought of this before -
function atom (T, v)
{ return Object.assign
( Object.create
( T.prototype
, { constructor: { value: T } }
)
, v
)
}
function pair (car, cdr)
{ return atom(pair, { car, cdr }) }
const p =
pair(1, 2)
console.log(p)
console.log(p instanceof pair)
Output -
{
"car": 1,
"cdr": 2
}
true
I wrote a small helper function which solves this problem. It effectively converts an ES6 class into an older ES5 constructor function which isn't subject to the same ruleset. This way you can create constructors which don't need new. You can also overload constructors in a similar way to the builtin Number, String etc.
function callableConstructor(c, f) {
function ret(...args) {
if(new.target) {
return new c(...args)
}
return f(...args)
}
ret.prototype = c.prototype
ret.prototype.constructor = ret
return ret
}
Test it below:
function callableConstructor(c, f) {
function ret(...args) {
if(new.target) {
return new c(...args)
}
return f(...args)
}
ret.prototype = c.prototype
ret.prototype.constructor = ret
return ret
}
// Usage
class Foo {
constructor(a, b) {
this.a = a
this.b = 2 * b
}
f() {
return this.a + this.b
}
}
Foo = callableConstructor(Foo, (...args) => new Foo(...args))
let foo = new Foo(2, 3)
console.log(foo) // Foo { a: 2, b: 6 }
console.log(foo.f()) // 8
console.log(foo instanceof Foo) // true
foo = Foo(2, 3)
console.log(foo) // Foo { a: 2, b: 6 }
console.log(foo.f()) // 8
console.log(foo instanceof Foo) // true
I came at this issue because I encountered the no-new "do not use new for side effects" eslint rule - which turns out it's a bad practice to use new for an object that is immediately discarded.
I still wanted to use the class syntax because I like it, but I agree that a regular class with new keyword for something that does not produce an object can be confusing.
The solution for me was simple. Define an unexported class in a module and export a function that instatinates it.
class SideEffects {
constructor() {
}
// ...
}
export function addSideEffects() {
// eslint-disable-next-line no-new
new SideEffects();
}
Yes, we are still using the new keyword, but it's used internally in the module and it's obvious from reading the module file that it's not a regular class - and the exported function also makes it clear that it does not create an object.
This might be a little contrived, but it works
function Foo(x){
"use strict"
class Bar {
constructor(x) {
if (!(this instanceof Bar)) return new Bar(x);
this.x = x;
}
hello() {
return `hello ${this.x}`;
}
}
return new Bar(x)
}
Foo("world").hello()
You can't use a class without the new constructor, in my case I didn't want to use the new constructor any time I wanted to use my class, so what you can do is to wrap your class as follows (in my case it's a Dates utils library):
const defaultOptions = {
defaultFormatOptions: 'dd/MM/yyyy'
}
class DatesClass {
constructor(date = new Date(), options) {
this.date = date
this.options = { ...defaultOptions, ...options }
}
get value() {
return this.date
}
add() {}
...
}
export default (date, options) => new DateClass(date, options)
// then you can use it as follow
import dates from 'path/to/yourClass/from/above'
dates(new Date()).add({ unit: 'day', qty: 2}).value

Categories