Why is the mental model crucial for learning programming languages?
# Dev NoteIntroduction
- This article uses JavaScript’s primitive types as examples, which may operate differently compared to other programming languages.
- The functioning of primitive types is different from that of objects and arrays, so we will focus solely on primitive types for this discussion.
What is a Mental Model?
A mental model refers to our cognitive process of anticipating how things will develop or how they will operate.
It may sound a bit academic, but for example, when we see a button in a user interface, we expect that this UI element is clickable and that clicking it may trigger a series of events. Thus, when users find that this UI does not behave as expected, they feel confused.
But why do we perceive such a UI as a button? On one hand, it’s due to our environment; on the other, it’s based on experience. Users have been judging buttons based on these principles since they started interacting with web pages, and naturally, this understanding extends to other web interfaces.
Take this knob, for instance. Why is our first instinct to think of turning it rather than pressing it? Because in everyday life, most circular mechanisms are usually adjusted by rotation, so we apply this rule to other contexts.

Or consider a door handle. Why do we not think of opening it by rotating but instead by pressing down on the handle? It’s because we have a certain understanding of how handles operate and expect that pressing down will open the door.

When learning a programming language, as we progress, we also develop a mental model of how that language operates, mentally compiling and anticipating how these lines of code will execute.
The Importance of Mental Models
Let’s illustrate this with a simple JavaScript code example.
let a = 3;
let b = a + 3;
a += 1;
console.log(b); // b
This is a very basic JavaScript code snippet. Experienced developers already know what the answer is and where the pitfalls lie. Now, suppose we apply a flawed mental model to interpret this code; we might arrive at the following conclusions.
1. Before a += 1 is executed:

2. After a += 1 is executed:

Naturally, since a has increased by 1, we might think to change the 3 inside the circle to 4.
Since b = a + 3, if a changes, then logically, the value pointed to by b should also change to 7. Therefore, someone with an incorrect understanding might confidently reply, “7.”
I want to emphasize that while the answer is incorrect, I do not believe this is entirely the learner’s fault. From a typical reasoning perspective, if I understand b = a + 3 as a formula, then when a += 1 happens, it’s reasonable to expect that b should also change.
Once learners adopt such a thought process, correcting their understanding in future learning becomes particularly challenging, often leading to bugs they cannot explain.
Where Did It Go Wrong?
In JavaScript, primitive values cannot be changed. This statement may seem short, but for beginners, it can be nearly impossible to grasp its fundamental meaning.
The correct operation should look like this:

Since any primitive type cannot change its value, we cannot directly alter the 3 in the circle to become 4 (3 + 1). Instead, we must create a new number, 4, and point a to it. The original 3 remains unchanged (the blue circle), so regardless of any changes to a, b’s value will remain unaffected.
Rather than quoting textbook statements like, “primitive values in JavaScript are immutable,” I prefer to explain it this way. This approach aids understanding and accurately reflects how JavaScript code operates in practice. Upon closer inspection, the two models are very similar, but the key difference lies in whether learners understand the characteristics and functioning principles of JavaScript primitive values.
Whether learners can apply this understanding across various examples depends on their mental model. If they continue to use the first flawed model, even after encountering the statement “primitive types are immutable” during their learning process, they are still likely to arrive at incorrect conclusions.
Related Posts
- Stop Using Access Keys AlreadyAccess Keys are an easily overlooked security risk on AWS. Use OIDC with IAM Roles so GitHub Actions can securely access AWS resources without any secrets.
- Database Primary Keys: AUTO_INCREMENT, UUID, and UUIDv7Backend developers often have to decide on a primary key: auto increment or UUID? What about collisions? How much faster is UUIDv7 compared with created_at + index? After benchmarking 20 million rows and looking at the design trade-offs, this post gives you the answer.
- Sharing My Experience with ZeaburIndependent developers often choose platforms like Vercel for deploying their services. However, when more advanced requirements arise, such as database connections, Vercel can become less convenient. Additionally, the pricing of typical cloud service providers can be quite expensive for solo developers. In this article, I’ll share some insights on using Zeabur and highly recommend it to everyone!
- Keyboard Enthusiast's Guide - Firmware EditionThis article is part of the IT 2023 Ironman Competition: A Beginner's Guide to Keyboards - Firmware Edition.