| name | simpson-you-dont-know-js |
| description | Write JavaScript code in the style of Kyle Simpson, author of "You Don't Know JS". Emphasizes deep understanding of JavaScript mechanics—scope, closures, this, prototypes, and async. Use when you need to truly understand JavaScript behavior. |
| tags | scope, closures, this, prototypes, async, promises, generators, coercion, types, deep-understanding |
Kyle Simpson Style Guide
Overview
Kyle Simpson is the author of the "You Don't Know JS" book series. His philosophy centers on truly understanding JavaScript's core mechanics rather than just memorizing patterns or avoiding features out of fear.
Core Philosophy
"The only way to understand JavaScript is to understand JavaScript."
"Don't fear what you don't understand—learn it."
"Coercion is not evil, it's just misunderstood."
Simpson believes that most JavaScript confusion comes from not understanding how the language actually works, not from the language being inherently broken.
Design Principles
-
Understand, Don't Memorize: Know why code works, not just that it works.
-
Embrace the Language: Use JavaScript as JavaScript, not as Java-lite.
-
Master the Core: Scope, closures, this, prototypes are essential.
-
Explicit Over Magic: Prefer explicit code even if longer.
When Writing Code
Always
- Understand what
this refers to in every function
- Know the difference between lexical and dynamic scope
- Use closures intentionally and understand their implications
- Understand coercion rules when using
==
- Know prototype chain behavior
- Understand event loop and async mechanics
Never
- Use
this without understanding its binding rules
- Ignore type coercion—understand it instead
- Assume
class hides JavaScript's prototype nature
- Use
async/await without understanding Promises
- Copy-paste code you don't understand
Prefer
- Understanding over avoidance
- Explicit type coercion (
Number(), String()) over implicit
- Factory functions or OLOO over
class (for clarity)
- Clear naming that reveals intent
- Comments explaining why, not what
Code Patterns
The Four Rules of this
function sayHello() {
console.log(this.name);
}
sayHello();
var person = {
name: 'Alice',
greet: function() {
console.log(this.name);
}
};
person.greet();
var greet = person.greet;
greet();
function introduce() {
console.log('I am ' + this.name);
}
var bob = { name: 'Bob' };
introduce.call(bob);
introduce.apply(bob);
var boundIntroduce = introduce.bind(bob);
boundIntroduce();
() {
. = name;
}
charlie = ();
.(charlie.);
team = {
: [, ],
: ,
: () {
..( {
.(member + + .);
});
}
};
Closures Demystified
function createCounter() {
var count = 0;
return function increment() {
count += 1;
return count;
};
}
var counter = createCounter();
counter();
counter();
counter();
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 100);
}
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, 100);
})(i);
}
for (let i = ; i < ; i++) {
(() {
.(i);
}, );
}
OLOO (Objects Linked to Other Objects)
var PersonPrototype = {
init: function(name) {
this.name = name;
return this;
},
greet: function() {
return 'Hello, I am ' + this.name;
}
};
var EmployeePrototype = Object.create(PersonPrototype);
EmployeePrototype.initEmployee = function(name, title) {
this.init(name);
this.title = title;
return this;
};
EmployeePrototype.introduce = function() {
return this.greet() + ', ' + this.title;
};
var alice = Object.create(EmployeePrototype)
.initEmployee('Alice', );
alice.();
Understanding Coercion
var num = Number('42');
var str = String(42);
var bool = Boolean('hello');
var result = '5' - 2;
var concat = '5' + 2;
null == undefined;
42 == '42';
true == 1;
'0' == false;
function isNullOrUndefined(val) {
return val == null;
}
Async Patterns Deep Dive
doA(function() {
doB(function() {
doC(function() {
});
});
});
function fetchData(url) {
return new Promise(function(resolve, reject) {
if (success) {
resolve(data);
} else {
reject(new Error('Failed'));
}
});
}
fetchUser(id)
.then(function(user) {
return fetchPosts(user.id);
})
.then(function(posts) {
return processPosts(posts);
})
.catch(() {
.(err);
});
() {
{
user = (id);
posts = (user.);
(posts);
} (err) {
.(err);
err;
}
}
Scope and Hoisting
function example() {
console.log(x);
var x = 5;
console.log(x);
}
function example() {
var x;
console.log(x);
x = 5;
console.log(x);
}
function example() {
console.log(x);
let x = 5;
}
sayHi();
function sayHi() {
console.log('Hi');
}
sayBye();
var sayBye = function() {
.();
};
Mental Model
Simpson approaches JavaScript by asking:
- What does
this point to? Apply the four rules
- What scope does this live in? Lexical, not dynamic
- What's in the closure? What variables are captured
- What's the prototype chain? Follow the
[[Prototype]] links
- What type coercion is happening? Know the algorithm
Signature Simpson Moves
- OLOO pattern instead of classes
- Understanding
this binding rules explicitly
- Safe
== usage when types are known
- Explicit coercion over implicit
- Deep async understanding before using
async/await