114

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
Damjan Pavlica
  • 31,277
  • 10
  • 71
  • 76
Mulan
  • 129,518
  • 31
  • 228
  • 259
  • 2
    Keep in mind a work-around is to just define a factory function (with a slightly different name) that just does `return new Foo(arg);`. – jfriend00 Jun 07 '15 at 07:43
  • Yeah I considered this but then there is an asymmetry between the constructor name and the class name :{ – Mulan Jun 07 '15 at 16:54
  • Interesting. JS programmers have gotten used to calling the constructor witbout the "new". Saves some typing, sometimes makes code seem more elegant, and a big source of bugs and confusion. Will be interesting to see how this practice changes in a few years. – user949300 Jun 07 '15 at 21:10
  • @user949300 i almost always use the `new` keyword. I intend to use this for something else tho. – Mulan Jun 08 '15 at 09:10
  • 4
    @user949300 I've already dropped javascript in favor of coffeescript. ES6 and ES7 contains a lot of genius features, but it's new `the ugliest` syntax is horrifying. And the new keyword is also ugly as hell. Just compare the `Foo().bar()` code with `(new Foo()).bar()`. It sucks. What is so important about creating new objects? Creating objects is a daily routine, I don't need a special syntax for it. – user619271 Feb 16 '16 at 09:06
  • Possible duplicate of [JavaScript: How to create a new instance of a class without using the new keyword?](http://stackoverflow.com/questions/1580863/javascript-how-to-create-a-new-instance-of-a-class-without-using-the-new-keywor) – Damjan Pavlica Sep 28 '16 at 11:55
  • In my opinion the simple approach is to add a static method to the class that calls `new` for you (and it can also do stuff like manage all instances of the class for you and so on at the same time). – podperson Dec 14 '22 at 21:59

21 Answers21

61

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) };
Pang
  • 9,564
  • 146
  • 81
  • 122
adeneo
  • 312,895
  • 29
  • 395
  • 388
48

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.

Pang
  • 9,564
  • 146
  • 81
  • 122
Adam Ples
  • 594
  • 5
  • 8
  • 2
    This is only working solution. All other answers do not work under some circumstances. Astonished how inaccurate StackOverflow rating system is that the only right answer in the bottom of the list. – Kos Jul 16 '17 at 17:31
  • 3
    @wandalen - it's clearly not the *only* working answer, in fact the right answer to the question is just *"no, it's not possible"*. This is a *different* answer, that uses proxies instead of instances created with `new`, and it's a neat way to deal with the problem. – adeneo Jan 18 '18 at 19:20
  • 1
    If the class is declared first, then you don't need to use different names for the Proxy and class. `class Foo {}; const Foo = new Proxy(Foo, {apply(target, thisArg, args) { return new target(...args) }})`. However, `Foo` now references the Proxy instead of the original class. – jordanbtucker Sep 04 '18 at 19:09
  • @Kos Not only is this the wrong answer to the problem, you don't even need to use `Proxy` to do what this answer does... This is not what `Proxy` is for... `_Foo` could literally be a regular JS `function` that does the exact same thing, and it would be more appropriate for it to be such. – Andrew Feb 05 '23 at 02:16
  • Also not mentioning that this doesn't give you any way to put in your own "this"... exactly what is required to simulate ES5 class inheritance. – kungfooman Jun 27 '23 at 10:29
32

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
Mulan
  • 129,518
  • 31
  • 228
  • 259
  • 13
    This deserves points. I really wonder whether adding `class` to JS was an improvement. This shows what JS code should look like. For people wondering why there is no `this` anywhere, the created object is just using the `x` that was passed in to the 'constructor' (arrow function). Whenever it needs to be mutated, it returns a *new* object. The objects are immutable. – Stijn de Witt Apr 06 '17 at 22:23
  • I wonder if it will optimize the functions into the prototype, though, or if it will create new functions for each object. Maybe with `Object.freeze` it will optimize? – yyny Oct 26 '17 at 21:46
  • 4
    it will create new functions – Mulan Oct 27 '17 at 00:18
  • I actually like to use this pattern when I can, but subclassing is hell with it. Granted, it wouldn't be terribly difficult to add a couple language features to off-set that, but they don't exist. – Benjamin Riggs Oct 30 '17 at 22:35
  • @BenjaminRiggs functional programmers don’t use subclassing - they use composition – Mulan Oct 30 '17 at 22:36
  • @naomik Building objects through composition is easy. The problem is that runtime-testing of whether or not an object satisfies an interface of a would-be class requires excessive `thing.hasOwnProperty('attribute') || thing.hasOwnProperty('other_attribute') || ...` checks. And even then, if those are method calls that have different type signatures, you're still screwed. – Benjamin Riggs Oct 30 '17 at 23:15
  • 1
    javascript doesn’t have interfaces; i don’t know what you’re talking about – Mulan Oct 31 '17 at 01:27
  • Yes, Javascript lacking interfaces is part of the problem. Surely you're familiar with the general concept of an interface to a class. In Javascript, you test that with the `instanceOf` operator. When you're creating objects purely through composition, that operator doesn't work, so you have to degrade to a bunch of OR'd `.hadOwnProperty` calls. And even those can fail because methods on objects with identical names can return different things. – Benjamin Riggs Oct 31 '17 at 17:35
  • Basically, functional programming is great when you're doing simple stuff, or when there's a robust type system. But doing complex functional programming in a language that uses classes as its type system, without using classes, is hard. – Benjamin Riggs Oct 31 '17 at 17:36
  • I guess I don’t understand what you’re getting at - I haven’t used `instanceof` or `.hasOwnProperty` in quite some time; not missing them - To me it sounds like your issue is trying to enforce an interface in a language without interfaces. I don’t share your struggle so I’m afraid I don’t know how to help you. Sorry :/ – Mulan Oct 31 '17 at 18:19
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/157954/discussion-between-benjamin-riggs-and-naomik). – Benjamin Riggs Oct 31 '17 at 22:21
  • 20
    The problem with technique is that each time Foo is invoked, it has to create all methods again. With classes, the `prototype` methods are efficiently shared between instances without having to re-create then per instance. Because the methods are re-created, you use up more memory as well. For production purposes, it is better to use something similar to the answer by Tim and use a method to create a new class. – Babakness Feb 20 '18 at 23:04
  • I've added an answer using `of` and references to the `Fantasy-Land` specs – Babakness Feb 20 '18 at 23:18
  • @naomik I've added a new answer https://stackoverflow.com/a/48911634/1560484, this one is similar to the one here except it doesn't create new functions each time. :-) – Babakness Feb 21 '18 at 17:09
  • This syntax made no sense to me until I realized it is equivalent to `const Foo = x => {return {x, ...}}`. – Daniel Sokolowski Apr 19 '18 at 03:18
  • Daniel, correct. It’s a function that returns an object ^^ – Mulan Apr 19 '18 at 03:31
  • What's wrong with the `new` keyword in the first place? For some reason it's considered a bad practice to use class for something of which no reference is held (side effects) but why? The alternatives are uglier and some are less performant too. – Maciej Krawczyk Dec 07 '21 at 19:37
  • If you actually like this approach consider defining the functions outside the assignment statement and using `this` instead of hard references to `Foo`. – podperson Dec 13 '22 at 20:45
  • @podperson nah, I would advise against that. the additional abstraction adds complexity without any positive gain. – Mulan Dec 14 '22 at 15:51
  • I like my code to work for more than one thing. That's a positive gain. But YMMV (and yes, `this` is generally to be avoided) – podperson Dec 14 '22 at 21:56
  • @StijndeWitt Surprised nobody has addressed this over all the years. What Babakness said, but also: JS classes both allow inheritance ([`extends`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends)), and, even if you don't care about that, they also allow automatic binding of the `this` keyword to each of the `class`'s functions, as well as "partial class" (defining classes in piecemeal) implementations. See my **comments** here for more: https://stackoverflow.com/a/71923547/1599699 https://stackoverflow.com/a/62142995/1599699 – Andrew Feb 05 '23 at 02:20
19

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 
Fareed Alnamrouti
  • 30,771
  • 4
  • 85
  • 76
16

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.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • This was the only solution that worked for what I wanted, as due to making a dynamic class heirarchy (mixins defined as classes instead of functions) I needed to be able to instantiate the base class with the child class' prototype. – Griffork Nov 25 '19 at 08:52
11
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.

Tim
  • 2,236
  • 1
  • 20
  • 26
  • 2
    Hint: classes that have only static members should not be `class`es but plain objects. In case of only a single member, they shouldn't even be at all. – Bergi Dec 17 '15 at 21:31
  • normally I wouldn't define the `create` method static. in this example I'm using `static`, because the creator wants to create objects without the `new` keyword. – Tim Dec 17 '15 at 21:36
  • 1
    Just if you didn't notice it: I'm talking about your `Strategy` classes. I hope you're not advocating to make `create` an instance method of those? `static` is totally fine. – Bergi Dec 17 '15 at 21:37
  • I'm talking about the strategies too. Don't really understand the problem. I only recommand to use a CreationStrategy, to create objects if they need "complex" logic. – Tim Dec 17 '15 at 21:45
  • 4
    In JavaScript, if you need to do a thing, you can just do it. You don't need to write a class and create an instance of it for that. That's ridiculous bloat. Just use a simple function. – Bergi Dec 17 '15 at 21:48
  • Why not use some es6 features? It helps you to organize your code. A lot of people complain about javascripts syntax or exception etc. So why don't write clear code and increase the usability? – Tim Dec 17 '15 at 21:55
  • 1
    Because declaring a `class` only to create a single function (and to call it a "method") **does not organise code**. Just declare the function. Do not use ES6 features only because they are there or because they make your code look like Java. – Bergi Dec 17 '15 at 21:58
  • That has nothing to do with java. And again: Its an example, to outsorce "complex" creation logic. "Please avoid extended discussions in comments. Would you like to...." – Tim Dec 17 '15 at 22:02
  • Well all those classes start looking very much like Java… and that's not a good thing. There's nothing wrong with outsourcing complex logic, but you don't need classes for everything. – Bergi Dec 17 '15 at 22:09
  • 1
    And in this particular case, where the creation logic *belongs* to the class, I don't see any reason to outsource anything. Just leave it in that `static create` method. – Bergi Dec 17 '15 at 22:10
6

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');
user2922935
  • 439
  • 4
  • 12
4

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.

Joseph
  • 117,725
  • 30
  • 181
  • 234
2

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() {}
131
  • 3,071
  • 31
  • 32
2

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;
}());
kasbah
  • 903
  • 5
  • 23
2

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

Babakness
  • 2,954
  • 3
  • 17
  • 28
  • I think I'm seeing a fixable problem, but I could be wrong. Each time we apply Right (eg `Right(1)`, `Right(2)`), the `Object.entries($methods).reduce` bit is called. I think you intend to perform this reduce only once. Is that correct? – Mulan Feb 21 '18 at 17:36
  • @naomik Thanks! Hmm... You still need to bind the new value(s) in the functor container to the methods on the functor you return? I just optimized the code by placing the reducer outside of the reduce function to prevent it from being re-created each call. – Babakness Feb 21 '18 at 17:53
  • *Hmm* indeed... but it makes sense at a fundamental level: Just taking `map: (x,f) => Right(f(x))`, if `x` is ever going to represent a different value, `map` must be re-`bind`ed with that value. Re-binding creates a new function, so we're back in the same boat. – Mulan Feb 21 '18 at 17:58
  • I just did some reading--you are right about that, I'll update my answer--in a world were bind is optimized to only partially apply to a function without re-creating it, maybe this code will become the new fashion :-) – Babakness Feb 21 '18 at 18:04
  • I'm going to play around with it a bit. Your edit still calls the `Object.entries( $methods ).reduce(` each time we construct a new value. Binding delays evaluation, so you'd have to address this in a different way. Thanks for sharing this fun exercise. – Mulan Feb 21 '18 at 18:09
  • So I can know about it, please share a link here to whatever you come up with while experimenting! – Babakness Feb 21 '18 at 18:15
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/165588/discussion-between-naomik-and-babak). – Mulan Feb 21 '18 at 18:19
  • This code just throws an error: VM60:4 Uncaught TypeError: Found non-callable @@iterator at reducer (:4:71) at Array.reduce () – kungfooman Jun 16 '22 at 12:36
2

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:

  1. In your class Foo, create a static method named 'new':

     static new (...args)
     { return new this (...args);
     } 
    
  2. 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.

Panu Logic
  • 2,193
  • 1
  • 17
  • 21
2

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:

  1. new A('NEW-A()')
    • output => "A's constructor seeing 'new' invoked on A with args: ['NEW-A()']"
  2. new B('NEW-B()')
    • output => "A's constructor seeing 'new' invoked on B with args: ['NEW-B()']"
  3. 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"
  4. 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).
smallscript
  • 643
  • 7
  • 13
1

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.

Vinod Srivastav
  • 3,644
  • 1
  • 27
  • 40
0

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
Sze-Hung Daniel Tsui
  • 2,282
  • 13
  • 20
0

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()

Babakness
  • 2,954
  • 3
  • 17
  • 28
  • In your third example, I see: `static of(x) { new _Foo(x)}` … What is the purpose of the underscore? Sorry if I am missing something obvious here. Thanks for the example! – mhulse Feb 09 '19 at 23:24
0

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
Mulan
  • 129,518
  • 31
  • 228
  • 259
  • 1
    On QKS Smalltalk engine [I wrote] from 1998 (unchanged since then) run today on 2.60 GHz Dell Laptop: => [100_000 fibonacci] millisecondsToRun => 286 ms => 100_000 fibonacci asString size => 20899 FYI: V8 was born of Animorphic Smalltalk 1994 (Lars Bak) => Java HotSpot => V8 JavaScript. Try running "30000 factorial" if you want to see how good-or-bad the GC and BigInt system is doing on JavaScript. (p.s., I was lead JavaScript architect at Microsoft for many years). – smallscript Nov 15 '21 at 09:40
  • 1
    impressive! i've always wanted to learn smalltalk but never into it. do you have any recommendations for getting smalltalk up and running in a modern macos environment? – Mulan Nov 16 '21 at 22:14
  • 1
    Check this out: http://wiki.squeak.org/squeak/2801 – smallscript Nov 18 '21 at 00:54
0

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
EnderShadow8
  • 788
  • 6
  • 17
  • See [Reflect.construct](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/construct) – Mulan Aug 01 '21 at 21:12
0

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.

Maciej Krawczyk
  • 14,825
  • 5
  • 55
  • 67
-3

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()
Josh
  • 59
  • 1
  • 1
  • 8
  • 2
    I'm confused, why would you have the `instanceof` check, since you aren't even exposing the class? This answer doesn't really address the main issue. – loganfsmyth Jun 08 '15 at 23:08
  • 2
    This also doesn't work because `Foo('world') instanceof Foo` returns `false`. – Mulan Jul 08 '15 at 16:07
-3

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
elverde
  • 193
  • 2
  • 7