-
-
Save myshov/05800f083a0afce56e0f782314a103eb to your computer and use it in GitHub Desktop.
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(); |
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
A 12th:
({
get accessorFunc() {
console.log(12);
}
}).accessorFunc; // this invokes the function
;((_ = 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]]]])
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")
I will just leave this here
function foo() {}
foo``
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
// 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);
console.log.bind(console)(12)
Haha, I don't think this is a compliment to the language ... ;)
And... the weirdest of all:
!function () { console.log(42) }()
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);
;)
Tagged template literals ftw!
[]["map"]["constructor"]("console.log(18)")()
The weirdest is far this one mentioned above:
function foo() {}
foo``
Styled components shocked the world with this syntax
var foo=function(d){console.log(d)}
foo`dd`
VM219:1 ["dd", raw: Array[1]]
any explanation?
@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
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 }
Does this count?
var i = document.createElement("img");
i.onerror = function() { console.log(1); };
i.src = "nope";
do not forget constructor without parenthesis so mainly 5 way.
function A () {};
new A;
A``;
A();
A.call();
A.apply();
with double colon bind operator:
console::(console.log)(0)
Promise.resolve(19).then(console.log)
console["log"](9)
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';
This thread has some interesting examples: https://stackoverflow.com/questions/35949554/invoking-a-function-without-parentheses
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
I think the correct way to invoke functions similar will be
console.log is generic function and does not use
this
context, so this works with null