
Ways to Invoke a Function in JavaScript - sr2
https://gist.github.com/myshov/05800f083a0afce56e0f782314a103eb
======
fred256
Number 2 is cheating IMHO: it is invoking console.log just like 1, just
wrapped in an immediately invoked closure. You can keep playing this game ad
infinitum:

    
    
        (_ => (_ => console.log("2a"))()()
        (_ => (_ => (_ => console.log("2b"))))()()()

~~~
kmill
I wasn't reading carefully, and I thought they mentioned it because it's
slightly different from

    
    
        (function () { console.log("#"); })();
    

though not actually since the this is not being used.

I was expecting to see

    
    
        console.log.bind(console)("#")
    

as well.

Edit: bind is farther down in the comments.

~~~
jmull
bind is a way to create a function, not invoke one. Here you're invoking the
function (that bind returned) in the normal way, using parenthesis.

~~~
kmill
The list seems to be about different ways a particular function could be
called, rather than just the syntax of invocation. Imagine you are making a
code analysis program and you want to find all the places console.log is
called; I imagined the bind example as encompassing things like

    
    
        var log = console.log.bind(console);
        // ... ... ...
        log("#");

~~~
jmull
Ok: static analysis of a language where most fundamental relationships are
resolved at runtime.

I guess this is one way to express the futility.

The lesson learned is hook console.log -- or whatever function you are
interested in -- meaning, replace it with something that captures the context
in which it is called and passes through the call to the original)

------
amelius
At least this one is cheating:

    
    
        (_ => console.log(2))();
    

This is creating a function from which the function (console.log) is invoked.
So not a direct call, but two calls instead.

~~~
jmull
A bunch of these are cheating... just wrapping () in various ways or accessing
call and apply in various ways. For general functions, I think the commenter
who says there are three ways to invoke a function is correct: (), call,
apply.

There are additional ways specific functions are called -- I'm thinking of
toString and valueOf.

~~~
underwater
Yeah, considering that `Function.prototype.apply === console.log.apply` there
are a lot of dupes here. I would consider eval/new Function to be a legitimate
fourth way though.

~~~
inimino
Eval is another way to run arbitrary JS code. It's cheating here because
nothing about the use of eval is specific to calling a function.

According to that standard, opening an external interpreter would be yet
another way.

Agree with the above that there are really only three ways here.

------
vmarquet
And the weirdest way of all to do a console.log(1):

    
    
        [][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]](([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()
    

How: [http://www.jsfuck.com/](http://www.jsfuck.com/)

As a side note, jsfuck is usefull for bypassing filters who try to prevent the
exploitation of XSS vulnerabilities.

~~~
indexerror
Except that any non-trivial code in JSfuck is enormous in size.

~~~
userbinator
Enormous but extremely compressible.

~~~
johnfn
It's almost like they convey the same amount of information or something .....

------
19eightyfour
Which one of these would be cheating?

    
    
        [...{[Symbol.iterator](){return {next(){ return {done:console.log(1)}}}}}];
        JSON.parse("[]",()=>console.log(1))

~~~
yladiz
Funny enough, if you take the first and put it into babeljs.io, it will cause
it to crash the tab.

~~~
19eightyfour
"Owned." Heh.

------
franciscop
Make accessing or setting a property to be an actual function call with Proxy:

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

log[11];

------
abalashov
And I assume that the fact of this multiplicity is not seen to be the
manifestation of a problem with the language? :-)

~~~
AgentME
If one is trying to find redundancy in the language, one might want to ignore
the redundant items in the list first:

* 2 and 8 are literally just 1 inside of a callback, which is weird to be this list. Might as well also have `var x = console.log(1);` while we're at it.

* 11 is some Nodejs specific way of making a new context and then running code on it. It's somewhat equivalent to doing this in bash: `echo "#!/bin/bash\necho 123" > script.sh && bash script.sh`. I think it's pushing it to call that a way to run a function within the language.

A few are natural consequences of how the `this` parameter and classes work in
Javascript. (Not to say that the way the `this` parameter and classes work in
Javascript is above criticism, but they do make certain kinds of behavior easy
that would require relatively painful reflection in Java to do, so if anything
one should compare them to Java's reflection APIs.)

* 4 shows the call method of functions, which lets you provide a different `this` parameter to a function call than the automatically inferred one. (In a regular call to `console.log(1)`, the log function from the console object is called with console as the `this` parameter and 1 as the first normal parameter.)

* 9 and 10 are just demonstrations of that all methods can be retrieved from the object that owns them or the class they came from.

Some of the kinda redundant-looking ones have uses which I think pays for
their existence:

* 6 is using an eval-like shortcut to parse a string into a callable function rather than executing it immediately, and unlike eval, it doesn't get access to variables within the current scope, which makes the code easier to analyze. Anywhere `eval` is used with a dynamic string, you've got to wonder about how it could screw with variables within the current scope.

* 5 is the way to supply a function with a variable number of arguments supplied by an array. ES6 has added some nice syntax sugar for this at least: `console.log(...someArray)`.

* 7 shows the `Reflect.apply` function, which is equivalent to `Function.prototype.apply.call`. The global `Reflect` object is provided as a convenience/demonstration as a default no-op pass-through implementation of a Proxy handler. There's almost no need to ever use the Reflect object outside of setting up a Proxy object. Calling it redundant would be like drawing an equivalence between tissues and toilet paper and wondering why anyone bothers buying toilet paper separately: it's because it's put into a convenient form-factor for a specific use.

