C++ certainly doesn't have a concrete virtual machine in the way JavaScript does, and C++'s abstract virtual machine certainly doesn't expose as many irrelevant implementation details of that virtual machine as JavaScript does. JavaScript's abstractions are much leakier than C++'s.

https://en.wikipedia.org/wiki/Leaky_abstraction

https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-a...

Don't get what I mean by leaky abstractions? Take non-fat-arrow functions for example. They're more expensive than fat-arrow functions, because they have a "prototype" property. And that's used to IMPLEMENT JavaScript's weird quirky form of object oriented programming, by giving you yet another way to call that function with "new" to create an object using that prototype, in a way that makes it a dangerous mistake to call that function the normal way without "new" (by sorta working on the surface usually without throwing an error, but causing deep subtle hard to diagnose bugs).

That is yet another double barreled footgun, thanks to a leaky abstraction with functions and "new": mistakenly calling a JavaScript class directly instead of using "new", or mistakenly calling "new" on a non-class function or fat arrow function, which doesn't have a prototype and can't be used as a class. Non-fat-arrow functions and "new" are like a footgun whose barrel is bent around aiming at the head of person who's shooting it. Fat-arrow functions don't solve the problem or eliminate the footgun, they merely add another barrel to the gun, aimed directly at your foot, too.

So if you can't directly call or apply a class function that has a prototype like a normal function, then why the hell is it a function anyway, instead just being a class like most other oop languages have, and why the hell does that irrelevant feature of functions having an optional prototype force that overhead on ALL the other functions in the system, whether or not they need it, even if you're using purely functional programming without objects?

That was one of the original rationals for fat arrow functions, as well as papering over the dynamic "this" binding mistake: to get rid of the overhead of the function prototype link, since non-class-constructor functions were so predominantly common. But they didn't bother to fix the obnoxious quirk about overloading functions with behaving like classes, but having to call them differently with "new", instead of simply having classes that were not callable functions, and being able to support multiple constructors with different names and signatures, like so many other object oriented programming languages do (but which JavaScript can't support, since class === function === constructor, there can only be one constructor per class by definition).

Conflating functions and classes and constructors is just insane, a pointless mistake and implementation detail with no upside and many downsides. That's what I call a functionally classic leaky abstraction. ;)

https://news.ycombinator.com/item?id=3780748

>mattbriggs on Mar 31, 2012 | parent | favorite | on: Douglas Crockford on Fat Arrow Functions in JavaSc...

>the this keyword still works exactly the same, just a terse syntax for functions and for function binding to the current scope.

>currently, function(){} is the exact same as the proposed ()->{}, and (function(){}).bind(this) is the exact same as ()=>{}

>starwed on Mar 31, 2012 [-]

>This is not just about syntax. Unless using bind somehow grants the mentioned property that

>>"Fat arrow functions do not have prototype properties, which makes them cheaper to make. They are immutable."

[That was quoting Douglas Crockford:
https://yuiblog.com/blog/2012/03/30/what-is-the-meaning-of-t... ]

>mattbriggs on Mar 31, 2012 [-]

>granted, but that sounds more like a micro optimization rather then significantly changing the behavior of the language

Perl originally had the exact same problem of leaky abstractions, only much much worse. The language design was deeply defined by nothing more than the one implementation of the Perl interpreter itself. There was no "abstract virtual machine" design written down. There was only the source code to the one existing implementation of Perl.

You had to understand many trivial details about how that one Perl interpreter just happened to be implemented, in order to truly understand Perl. (Try explaining Perl references without making all kinds of nuanced excuses and implicit references to how the Perl interpreter itself works.)

It took Perl (or whatever the kids are calling it these days) decades and decades to dig its way out of that hole, and by the time they did, it was irrelevant. JavaScript got a lot luckier.