Skip to content

Instantly share code, notes, and snippets.

@myshov
Last active August 19, 2024 12:23
Show Gist options
  • Save myshov/05800f083a0afce56e0f782314a103eb to your computer and use it in GitHub Desktop.
Save myshov/05800f083a0afce56e0f782314a103eb to your computer and use it in GitHub Desktop.
11 Ways to Invoke a Function
console.log(1);
(_ => console.log(2))();
eval('console.log(3);');
console.log.call(null, 4);
console.log.apply(null, [5]);
new Function('console.log(6)')();
Reflect.apply(console.log, null, [7])
Reflect.construct(function(){console.log(8)}, []);
Function.prototype.apply.call(console.log, null, [9]);
Function.prototype.call.call(console.log, null, 10);
new (require('vm').Script)('console.log(11)').runInThisContext();
@Delagen
Copy link

Delagen commented Apr 7, 2017

I think the correct way to invoke functions similar will be

console.log.call(console, 4);
console.log.apply(console, [5]);
Reflect.apply(console.log, console, [7])
Function.prototype.apply.call(console.log, console, [9]);
Function.prototype.call.call(console.log, console, 10);

console.log is generic function and does not use this context, so this works with null

@mrtbld
Copy link

mrtbld commented Apr 7, 2017

console.log is generic function and does not use this context

That's not exact, it does use this [0], it's just that it's pre-bound to the Console instance [1]. (At least in node.js.)

But your right, those examples wouldn't work for methods that aren't bound to their instance, which is what happens by default.

[0] https://github.com/nodejs/node/blob/a94a5da78c6fdecf1aef541db237a1c96a9801a3/lib/console.js#L103-L108
[1] https://github.com/nodejs/node/blob/a94a5da78c6fdecf1aef541db237a1c96a9801a3/lib/console.js#L57-L62

@ashsearle
Copy link

A 12th:

({
  get accessorFunc() {
    console.log(12);
  }
}).accessorFunc; // this invokes the function

@Jessidhia
Copy link

Jessidhia commented Apr 7, 2017

;((_ = console.log(13)) => {})()
;(class extends (console.log(14), null) {}) // cheating maybe?
// this can always go deeper
Function.prototype.apply.apply(Function.prototype.apply, [Function.prototype.apply, [console.log, [console, [15]]]])

@blindman67
Copy link

blindman67 commented Apr 7, 2017

do these count?

;(console.log)(16)
{let a;( a="log",console[a])(17)}
{let t,b;(t=this,b=(a)=>t=t[a],["console","log"].forEach(b),t(18))}
{let t,b,c="console.log";(t=this,b=(a)=>t=t[a],c.split(".").forEach(b),t(19))}
((...a)=>this[a[0]][a[1]](20))("console","log")

@bahmutov
Copy link

bahmutov commented Apr 7, 2017

I will just leave this here

function foo() {}
foo``

@Vanuan
Copy link

Vanuan commented Apr 7, 2017

There are only 3 ways:

var message = 'message';
console.log(message); // 1
console.log.call(console, message); // 2
console.log.apply(console, [message]); // 3, array-like 'call'

Other "ways" are just ways to access either call/apply methods or a function to be called.

(_ => console.log(2))(); // Way 1 + IIFE (which is also way 1)
eval('console.log(3);'); // Way 1 + eval
new Function('console.log(6)')(); // Way 1 + new Function
Reflect.apply(console.log, null, [7]) // Way 3 + Reflect alias for Function.prototype
Reflect.construct(function(){console.log(8)}, []); // Way 1 + Reflect alias for new Function
Function.prototype.apply.call(console.log, null, [9]); // Way 3 using prototype form
Function.prototype.call.call(console.log, null, 10); // Way 2 using prototype from
new (require('vm').Script)('console.log(11)').runInThisContext(); // Way 1 + obscure way to use eval

@WebReflection
Copy link

// browser, sync
setTimeout('console.log(12)');

// node and browser, sync
new function () { console.log(13) };
(s => console.log(s[0]))`14`

// node and browser, async
setTimeout(console.log, 0, 15);

@getify
Copy link

getify commented Apr 7, 2017

console.log.bind(console)(12)

@polterguy
Copy link

Haha, I don't think this is a compliment to the language ... ;)

@lirantal
Copy link

lirantal commented Apr 7, 2017

And... the weirdest of all:

!function () { console.log(42) }()

@salomvary
Copy link

Function.prototype.call.call(console.log, null, 12);
Function.prototype.call.call.call(console.log, null, 13);
Function.prototype.call.call.call.call(console.log, null, 14);
Function.prototype.call.call.call.call.call(console.log, null, 15);
Function.prototype.call.call.call.call.call.call(console.log, null, 16);
Function.prototype.call.call.call.call.call.call.call(console.log, null, 17);

;)

@wesleysmyth
Copy link

Tagged template literals ftw!

@crcdng
Copy link

crcdng commented Apr 8, 2017

[]["map"]["constructor"]("console.log(18)")()

@leonardoanalista
Copy link

The weirdest is far this one mentioned above:

function foo() {}
foo``

Styled components shocked the world with this syntax

@pwang2
Copy link

pwang2 commented Apr 8, 2017

var foo=function(d){console.log(d)}
foo`dd`
VM219:1 ["dd", raw: Array[1]]

any explanation?

@davidmarkclements
Copy link

davidmarkclements commented Apr 8, 2017

@pwang2 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Template_literals

another form of IIFE (makes function into expression) but I think it's semantically nicer:

void function () { console.log('19') }()

Also in terms of "hidden" or unexpected execution:

var o = {toString: () => console.log('20')}
var n= +o //20
~o //20
o + ''  //20
var s = `${o}` //20
o[o] //20
parseFloat(o, 10) //20
o++ //20
var o = {valueOf: () => console.log('21')}
var n= +o //21
~o //21
o + ''  //21
var s = `${o}` //21
o[o] //21
parseFloat(o, 10) //21
o++ //21
var o = {[Symbol.toPrimitive]: () => console.log('22')}
var n= +o // 22
~o //22
o + '' //22
var s = `${o}` //22
o[o] //22
parseFloat(o, 10) //22
o++ //22

node only:

var o = {inspect: () => console.log('23')}
console.log(o) // 23

You can also make functions calls for any object (that isn't pure - e.g. inheriting from null)

Object.prototype.toString = () => { console.log('24') }
Object.prototype.valueOf = () => { console.log('25') }
parseFloat({}, 10) //24
''[{}] // 24
1 + {} // 25
1 + function () {} // 25
Object.prototype[Symbol.toPrimitive] = () => { console.log('26') }
parseFloat({}, 10) //26
''[{}] // 26
1 + {} // 26
1 + function () {} // 26

And then there's meta programming for side effect calls:

var p = new Proxy({}, {
  has: (t, k) => {
    console.log('27')
    return true
  }
})


if ('foo' in p) {}  // 27
with (p) {
  moo + shoe //27 27
}

Object.prototype.hasOwnProperty = new Proxy(Object.prototype.hasOwnProperty, {
  apply: (t, self, args) => {
    console.log('28')
    return t.apply(self, args)
  }
})

var o = {}

if (o.hasOwnProperty('a')) {} // 28

@davidmarkclements
Copy link

As one liner "function calls":

+{[Symbol.toPrimitive]: () => console.log('x')}
+{toString: console.log.bind(console, 'x')}
+{valueOf: console.log.bind(console, 'x')}
'x' in (new Proxy({}, {has: () => console.log('x')}))
with (new Proxy({}, {has: () => (console.log('x'),1)})) callThatThing

More:

({get x() { console.log('x') }}).x
Object.create(null, {x: {get: () => console.log('x')}}).x

v8 only (node, chrome):

Error.prepareStackTrace = () => console.log('x'); Error()
Error.prepareStackTrace = () => console.log('x'); try { u } catch(e) { e }

@SpencerJobe
Copy link

SpencerJobe commented Apr 9, 2017

Does this count?

var i = document.createElement("img");
i.onerror = function() { console.log(1); };
i.src = "nope";

@garaboncias
Copy link

do not forget constructor without parenthesis so mainly 5 way.
function A () {};
new A;
A``;
A();
A.call();
A.apply();

@gonzaloruizdevilla
Copy link

with double colon bind operator:
console::(console.log)(0)

@jorrit
Copy link

jorrit commented Apr 11, 2017

Promise.resolve(19).then(console.log)

@guillermo
Copy link

guillermo commented Jun 18, 2017

console["log"](9)

@franciscop
Copy link

Using Proxy (not yet mentioned) you can make accessing, setting, etc a property to be an actual function call:

const log = new Proxy(console.log, {
  get: (orig, key) => orig(key)
});

log[11];

Based on this awesome/awful feature I created a little monster:

const buttons = dom.button.html;
dom.a.html = 'Hello world';

@jonbri
Copy link

jonbri commented Jun 19, 2017

@o0101
Copy link

o0101 commented Jun 19, 2017

I'm a fan of this one:

(class { [console.log(1)](){} })
({[console.log(1)](){}})
(function z( a = console.log(1) ){})()
[...{[Symbol.iterator](){return {next(){ return {done:console.log(1)}}}}}]; // hehe
try{[1,2,3][~~(Math.random()*4)].toString()}catch(e){console.log(12)}; // nondeterministically run console.log 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment