"What historical reasons?"
In a very early version of C, both bitwise AND and logical AND were just &
and it depended on context! And to make it easier to convert existing code, they kept the associativity rule of the logical AND for &
...
(Source: https://www.nokia.com/bell-labs/about/dennis-m-ritchie/chist.html)
@vaporeon_ i like javascript but it is chock full of nasty corners like this fur this exact reason
no image desc
@aescling @vaporeon_ @aescling @vaporeon_ The void
keyword:
void (expression)
is a shorthand for (expression), undefined
. That is, void
evaluates its operand and returns undefined
. It was introduced to enable the following idiom:
<a href="javascript:void doAThing()">Click me to do a thing :3</a>
"javascript:" is a URL protocol that allows the user to write javascript to represent the response of a hyperlink. Whatever follows after "javascript:" will be evaluated, and if the expression is a string, it is treated as if it were a HTTP/HTTPS response document and the browser navigates to that page. (If navigation occurs, the URL does not change and no history entry is created.)
When associating a tag with javascript It was often desirable for pressing the link to NOT induce page navigation and instead simply perform a side effect. This is guaranteed if what follows "javascript:" is preceded by the void keyword.
var hoisting:
The JavaScript interpreter can be thought to have a "preprocessor" phase where all variable declarations are found and initialized. This means that it is possible to use a variable before it is declared since that variable will already be initialized from the "preprocessor" phase.
This pattern is called "hoisting". Since function declarations are also initialized during preprocessing, functions can also be hoisted. Combine this with the fact that variables declared with var are not block-scoped and you can get into some very confusing situations. I have encountered real production code which hoisted a variable declared within a switch statement containing hundreds of lines .
A tangent:
This is a bit tangential to what you asked but I think you'll find it amusing. Go see what the result of ('b' + 'a' + + 'a' + 'a').toLowerCase() is :]
A unique comment directive:
I can't explain this better than how it is described in "JavaScript: the first 20 years", which is a wonderful historical document available for free as a PDF here: https://dl.acm.org/doi/10.1145/3386327. (I plagiarized some of its content in this toot actually.)
While I'm admitting my sources I should mentioned that I consulted MDN's JavaScript documentation frequently for this post.
re: no image desc
@wallhackio @aescling Backward compatibility for Netscape 1 and Mosaic, in 2015
Go see what the result of ('b' + 'a' + + 'a' + 'a').toLowerCase() is
How does this work? It looks as if the + +
adds a NaN, but if I do e.g. 1 + + 1
, it returns 2, unlike 1 + NaN + 1
, which returns NaN...
re: no image desc
@vaporeon_ @aescling + inexplicably is also a unary operator that, in some contexts, will try to convert its operand to a number
re: no image desc
@wallhackio @aescling Ooh! So e.g. +3
is 3, but +'a'
is NaN! Makes sense
(Dynamically typed languages are such a mess...)
re: no image desc
@vaporeon_ @aescling reported.
re: no image desc
@wallhackio @aescling For what? Trying to figure out your JavaScript code?
re: no image desc
@vaporeon_ @aescling javascript slander is a reportable offense.
re: no image desc
@vaporeon_ @aescling (+ converting things to numbers is stupid though, i agree.)
a (very) non-exhaustive list of strange corners in js
@vaporeon_ a lot of it is really whack decisions that got made early on that have to remain supppurrted fur compatibility reasons
myObject.myPurropurrty
is equivalent tomyObject['myPurropurrty']
; the latter works with all string expurressionslength
purropurrty). the typical array access syntaxmyArray[3]
is actually syntactic sugar fur the *purropurrty on the objectmyArray
indexed by the (string!) key'3'
—the3
is coerced into a string under the hoodarguments
in scope, which acts like an array but is technically not an array, allowing arbitrary access to any numbered argument on the function. (all functions are allowed to be invoked with any number of arguments). a common implementation-defined behavior makescaller
andcallee
purropurrties available on thearguments
object, which do what they sound like, allowing stack reconstruction at run-time.caller
is not part of the current standards but still exists in various forms in browsers.callee
is standardized but deprecatedthis
this
. what thethis
keyword may refur to in a given snippet is very unintuitivefloat
==
equality testing oppurrator coverts both sides of the expurression to the same type befur testing true equality on the converted values. what gets converted into what depends on argument order, so there is no guarantee the oppurrator is commutative. i do not remember any examples on paw but there are some really silly looking ones