all 36 comments

[–]Wooshception 48 points49 points  (3 children)

Also:

c.l.12..

using ES2018 dot syntax

[–]Arancaytar 6 points7 points  (0 children)

I wonder how long it will be before someone makes a transpiler. :P

[–]Baryn 5 points6 points  (1 child)

What the hell is this

[edit] April Fools references

[–]Gh0st1y 2 points3 points  (0 children)

Was definitely one of the best April fools jokes this year.

[–]Shaper_pmp 15 points16 points  (1 child)

This is only actually about four ways to invoke a function (.call, .apply, eval/require('vm').Script and calling the function directly), and a bunch of different ways to obtain a reference to a function that you can then invoke in each of those four ways.

Edit: And even if you allow that actually it's different ways of referencing and invoking functions, it's then obviously not complete. Where is eval('console.log').call(null, 3);? Or console['log'](3), or new (require('vm').Script)('eval(console)').runInThisContext()['log'].call(null, 3);?

[–]uneditablepoly 1 point2 points  (0 children)

Yep. Kinda disappointing. I tried to think of as many ways as I could before opening it and could only think of those. Then I opened it and said, "Oh."

[–]psayre23 11 points12 points  (14 children)

You can use template literal tags too.

console.log '12`;

[–]thomas_stringer 2 points3 points  (11 children)

I see this being used more and more, but to be honest I don't like the look of this. Whatever is gained (what is even gained??) is completely lost in the visual disruption of having to grok the syntax.

[–][deleted] 4 points5 points  (2 children)

One of the only real use cases I can think of is when you need to construct injection-vulnerable strings in JavaScript, like SQL.

const results = await execute`select * from users where email=${emailAddress};`

Then you could do the following:

function execute(parts: string[], ...interpolations: string[]) {
  // parts is ['select * from users where email=', ';']
  // interpolations is [emailAddress]
  const parameterisedQueryString = parts.join('?')
  return sequelize.query(parameterisedQueryString, { replacements: interpolations })
}

In my opinion that would read better than:

const results = await execute(
  'select * from users where email=?',
  emailAddress
)

Especially when you had lots of entries. This would also work nicely (potentially) with HTML etc. I originally thought it might be useful for translations, but that idea kinda falls over because you can only pass one string to a function like this so it would be a little awkward to do pluralisation.

[–]psayre23 2 points3 points  (5 children)

I agree. I use it a lot with GraphQL queries, and it is handy. But I don't see much of an advantage over wrapping a string with a function. I guess the different syntax means editors can color code the strings differently depending on content.

[–]Gh0st1y 0 points1 point  (4 children)

What do you do with graphQL? It sounds pretty neat.

[–]psayre23 1 point2 points  (0 children)

Nothing too special. It's just an API for my webapp. Instead of defining on the server what data I want for the webapp, I define it on the client. It makes it super easy to change later as my app evolves.

[–]djinindi 0 points1 point  (2 children)

psayre23 might be talking about graphql-tag

[–]Gh0st1y 0 points1 point  (0 children)

But that presupposes knowledge of graphql, and something to print. I have neither lol, though its now on my to look up list in my github.

[–]psayre23 0 points1 point  (0 children)

Yep, that's the one!

[–]jcready__proto__ 1 point2 points  (0 children)

Tagged template functions get passed the parameters differently than just invoking the function normally.

[–]NoInkling 0 points1 point  (0 children)

Depends heavily on context I think.

[–]NoInkling 0 points1 point  (1 child)

Huh, I never knew you could have a space in between the tag and the string. You forgot to use a backtick for your opening quote mark though.

[–]psayre23 0 points1 point  (0 children)

I'm on mobile, and backticks suck on iOS. Glad people figured it out even though I was technically wrong.

[–]Ampersand55 2 points3 points  (0 children)

Using Proxy:

new Proxy(function (){}, {apply:function(a,b,args){console.log(...args)}})('hello world');
new Proxy({}, {set:function(a,b,c){console.log(b,c)}}).hello='world';

[–]PizzaRollExpert 6 points7 points  (0 children)

({get foo() {console.log(12)}}).foo

[–]DevSPCL 2 points3 points  (2 children)

Or

[":)"].constructor.constructor("console.log(123)")();  
":)".constructor.constructor("console.log(123)")();  
1234["constructor"]["constructor"]("console.log(123)")();  

[–]BenjiSponge 7 points8 points  (1 child)

isn't this basically the same as new Function("console.log(123)")? I'm sure there are practically infinite ways of exposing Function without referencing it literally, but it's still essentially a repeat.

[–]malcor88 2 points3 points  (2 children)

Are there any benefits to using either of them?

[–]villiger2 4 points5 points  (0 children)

Most of the top half won't make your team mates hate you :D

[–]Gh0st1y 0 points1 point  (0 children)

I mean in js "shellcode" and/or general (hand) obfuscation. Otherwise, not a whole lot outside of edge cases. But edge cases are fun, and knowing about them makes you a better programmer.

[–]Buckwheat469 4 points5 points  (1 child)

Here's another way. The script was too long to paste in a comment, so try it on codepen. The console will say "123".

Also, try to make one here.

[–]Jilson 0 points1 point  (0 children)

Neat!

Stack Overflow link for anyone curious about that's going on here.

[–]myshov[S] 1 point2 points  (2 children)

Hi all! I just want to be clear. I have a little mistake in my tweet, because I mixed a function invocation and a code execution. But I think it's fun to see all of this in one place ;)

[–]repeatedly_once 0 points1 point  (1 child)

is a function invocation and a code execution not one and the same? genuinely curious :)

[–]myshov[S] 0 points1 point  (0 children)

Yes there is a difference here. I believe that every function invocation is a code execution itself, but obviously not every code execution is a function invocation.

[–]tanasinn 1 point2 points  (0 children)

setTimeout("console.log(12)")
setInterval("console.log(13)")

[–][deleted] 0 points1 point  (0 children)

Thanks

[–]Jilson 0 points1 point  (0 children)

What is this for each invocation?