Well, in that case the abstraction of private methods isn’t good either because there are ways to bypass them in C++ by passing a function pointer or in C# via reflection.
However, I would say there's some difference in severity between a surprising behavior that results from the intersection between two features, and a surprising behavior that results because the way a feature is described is literally inaccurate.
You can break Javascript classes without using any other feature of the language. You don't have to resort to something like Proxies, or overriding native prototypes. This is because it's not that other parts of Javascript provide escape hatches to get around behavior, it's that the class syntax itself does not cover the entirety of the prototype system it is trying to obscure.
It's not ideal to have any breakage in an abstraction, but some breaks are worse than others. To me, edge cases like this:
let foo = function () { this.x = 5; }
class Bar extends foo { //No error? But why?
constructor () { super(); }
}
foo = function () { this.x = 7; }
console.log((new Bar()).x); // 5, not 7 or undefined.
are on a whole nother level of leaky abstractions over even some of the worst parts of C#. To me, this is an edge case that nearly any reasonably imaginative student would likely find at some point using only very basic components of the Javascript language. And I have no idea how I would even begin to tackle explaining this without saying, "Okay, throw out everything I taught you about classes, here's how the language really works."