What Learning JavaScript Taught Me About How Little I Really Knew
I’ve been reading a book on JavaScript lately.
It’s an interesting experience: the material itself is dry, yet it happens to be exactly the kind of dry material I’m drawn to. I keep reading until I get sleepy, then after waking up I immediately want to pick it back up.
What makes the book so compelling is that, although it is about JavaScript, it spends very little time on the browser environment. Instead, it keeps probing the language itself—its fine structure, its edges, its underlying logic. Through that lens, a lot of things that have been worn smooth or hidden away by IE, Firefox, Chrome, Opera, and years of web design and framework practice suddenly become visible again. And once you see them, many things click into place.
That was the moment I realized how partial my understanding of JavaScript had been.
It also broke a few of my old assumptions:
- Good technical books are not written only by foreign authors; people here can write books with real depth too.
- Code and products that feel almost like works of art are not created only by some mythical elite; that potential exists in ordinary people as well.
- Starting early is not the only path. JavaScript itself has only been around for a little over a decade, and from the author’s own life story it seems clear that if the determination is there, it is never too late to become truly capable.
So here is a rough mid-course整理 of the blind spots and structural pieces of knowledge this book has helped me notice.
Things I thought I understood about JavaScript, but didn’t
Values and references are not the same thing
'abc' and new String('abc') are different in an essential way: the former is passed as a value, while the latter is a reference.
That distinction sounds basic, but in practice it affects how comparison and conversion behave, and it exposes how easily JavaScript lets wrapper objects blur the line between primitive values and objects.
A string can be written across multiple lines without containing line breaks
A string value can be written like this:
var str = 'abcdefg\
hijklmn\
opqrst\
uvwxyz';
The backslash here means the source code continues on the next line. The backslash itself is not part of the string, so the resulting value is still a 26-character string with no newline characters in it.
One detail matters: there cannot be a comment after the backslash.
== and === follow different comparison rules
I had a much fuzzier understanding of this than I thought. A useful way to think about it is:
<table> <thead> <tr> <th>Operator</th> <th>Comparing two literals</th> <th>Comparing a literal and a reference</th> <th>Comparing two references</th> </tr> </thead> <tbody> <tr> <td>==</td>
<td>Compares whether their values are equal</td>
<td>Converts the reference to a value first, then compares it with the other value</td>
<td>Compares whether the references are the same</td>
</tr>
<tr>
<td>===</td>
<td>Compares both type and value</td>
<td>Definitely not equal</td>
<td>Compares whether the references are the same</td>
</tr>
<tr>
<td>>, <, etc.</td>
<td>Compares the ordering of the two sequences directly</td>
<td>Converts the reference to a value first, then compares it with the other value</td>
<td>Cannot be compared; directly returns false</td>
</tr>
</tbody>
</table>
Even if this is not the whole story of JavaScript coercion, this framework already clears up many cases that used to feel arbitrary.
Regular expressions can use backreferences
In regular expressions, “reference matching” can be written like this:
(\d)\.\1
That means a digit, followed by a dot, followed by the same digit again.
Named function expressions do not necessarily leak into the outer namespace
In the SpiderMonkey JavaScript engine—the one used by Firefox and related environments—a named function inside an expression does not become part of the surrounding global namespace. For example:
((function foo(a,b) {...})(x,y));
The name in that form exists for the function expression itself rather than as a general name injected everywhere.
eval executes a complete statement, not just an expression
A subtle but important point: inside eval, what belongs there should be a complete statement rather than merely an expression.
The function performs three things in sequence:
- parse the statement
- execute the statement
- return the statement’s return value
That makes eval feel less like a magical shortcut and more like a full miniature execution step.
Even control-flow syntax has forms I rarely notice
Logical statements can be written in compact forms such as:
while (...);
if (...);
else {...}
These look odd at first glance, but they are valid, and understanding them helps when reading unfamiliar or deliberately minimal code.
Labels and labeled break are real language features
JavaScript supports labels, along with a less commonly seen use of break:
my_label: {
...
break my_label;
...
}
continue has a similar kind of usage.
This is one of those features many people can go a long time without using, but once you know it exists, certain pieces of code become easier to read instead of seeming bizarre.
new constructor(); can be shortened
When there are no arguments, new constructor(); can be shortened to new constructor;
What matters here is that constructor() in this case should not simply be treated as an ordinary function call.
Hidden properties are not always hidden forever
If an object’s implicit properties—such as some native-code-backed ones—are overwritten, then in some JavaScript engines they can become explicit properties, meaning they may start appearing in a for ... in loop.
That is the kind of engine-dependent behavior that can quietly surprise you if you assume built-in things will always remain invisible.
delete has limits
Some things cannot be deleted with delete:
- variables declared with
var - members on an object’s prototype
This is another place where JavaScript’s object model is more specific than the casual mental model many of us carry around.
in is a direct way to test for a property
You can check whether an object has a given property with:
if (property in object) {...}
Simple as it is, this belongs in the core toolkit.
A language I thought I knew
I’m not even done with the book yet, and it already feels like there is much more in it that can help fill out a more complete JavaScript knowledge system. For now, this is just a stage-by-stage整理 for myself—something to pin down before the next round of understanding shifts again.