denysdovhan / wtfjs

🤪 A list of funny and tricky JavaScript examples
http://bit.ly/wtfjavascript
Do What The F*ck You Want To Public License
34.97k stars 2.55k forks source link

Class Extends Function: Extra Newness #78

Closed joedski closed 3 years ago

joedski commented 6 years ago

I present this as an oddity for your amusement.

class Foo extends Function {
  constructor(val) {
    super();
    this.prototype.val = val;
  }
}

new new Foo(':D')().val // => ':D'

Constructors in Javascript are of course just functions with some special treatment. by extending Function using the ES6 class syntax you create a class that, when instantiated, is now a function, which you can then additionally instantiate.

While not exhaustively tested, I believe the last JS statement can be analyzed thus:

(new (new Foo(':D'))()).val
(new newFooInstance()).val
veryNewFooInstance.val
':D'

As a tiny addendum, doing new Function('return "bar";') of course creates a function with the body return "bar";. Since super() in the constructor of our Foo class is calling Function's constructor, it should come as no surprise now to see that we can additionally manipulate things in there.

class Foo extends Function {
  constructor(val) {
    super(`
      this.val = arguments[0];
    `);
    this.prototype.val = val;
  }
}

var foo = new new Foo(':D')('D:');
foo.val // -> 'D:'
delete foo.val; // remove the instance prop 'val', deferring back to the prototype's 'val'.
foo.val // -> ':D'
denysdovhan commented 3 years ago

Added to the list and will be released soon! Thanks a lot!

github-actions[bot] commented 3 years ago

:tada: This issue has been resolved in version 1.17.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket: