Skip to content

Commit b77b295

Browse files
committed
feat(i18n): translate JavaScript chapter 9 metaprogramming lessons to English
1 parent 0e2ab8b commit b77b295

3 files changed

Lines changed: 338 additions & 0 deletions

File tree

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
{
2+
"lessonId": "js-9-1",
3+
"title": "Proxy & Reflect (Metaprogramming)",
4+
"concept": "A Proxy acts as an 'Interceptor' that sits in front of a target object, trapping and redefining its fundamental operations.",
5+
"content": {
6+
"code": "const target = { \n secret: 'shhh',\n public: 'hello'\n};\n\nconst handler = {\n // 1. Trap that intercepts read (Get) operations\n get(obj, prop) {\n if (prop === 'secret') {\n return 'Access Denied!';\n }\n // 2. Forward the rest to the original object (Forwarding)\n return Reflect.get(obj, prop);\n }\n};\n\n// Creating a Proxy that wraps the original (Target)\nconst proxy = new Proxy(target, handler);\n\nconsole.log(proxy.public); // hello\nconsole.log(proxy.secret); // Access Denied!",
7+
"steps": [
8+
{
9+
"title": "Creating the Target object",
10+
"explanation": "This is the original object `target` that will be proxied.\nIt holds the actual data (the Real Subject) that the Proxy will wrap.",
11+
"visualizationType": "memory",
12+
"memoryState": {
13+
"heap": [
14+
{
15+
"address": "0xTarget",
16+
"content": "{ secret: '...', public: '...' }"
17+
}
18+
]
19+
},
20+
"code": "const target = {",
21+
"highlightOffset": [
22+
0,
23+
1,
24+
2,
25+
3
26+
]
27+
},
28+
{
29+
"title": "Defining the Handler and Traps",
30+
"explanation": "The `handler` object defines the rules of behavior for the Proxy.\nHere, the `get` method is a **Trap**.\n\n**What is a Trap?**\nA method that intercepts a fundamental object operation (read, write, call, etc.) and runs in its place.\nIn this case, it intercepts 'property reads'.",
31+
"visualizationType": "memory",
32+
"memoryState": {
33+
"note": "Handler prepared with 'get' trap"
34+
},
35+
"code": "const handler = {",
36+
"highlightOffset": [
37+
0,
38+
1,
39+
2,
40+
3,
41+
4,
42+
5,
43+
6,
44+
7
45+
]
46+
},
47+
{
48+
"title": "Creating the Proxy instance",
49+
"explanation": "`new Proxy(target, handler)` creates a proxy that wraps the original object.\nFrom now on, all access goes through this `proxy` object and follows the handler's rules.",
50+
"visualizationType": "memory",
51+
"memoryState": {
52+
"stack": [
53+
{
54+
"name": "proxy",
55+
"value": "→ 0xProxy"
56+
}
57+
],
58+
"heap": [
59+
{
60+
"address": "0xTarget",
61+
"content": "{ ... }"
62+
},
63+
{
64+
"address": "0xProxy",
65+
"content": "Proxy(Target, Handler)",
66+
"label": "Interceptor"
67+
}
68+
]
69+
},
70+
"code": "const proxy = new Proxy(target, handler);"
71+
},
72+
{
73+
"title": "Accessing properties through the proxy",
74+
"explanation": "We access `proxy.public` and `proxy.secret`.\nThe `get` trap intercepts both.\nThe 'public' property is forwarded to the original via Reflect.get (returns 'hello'), while 'secret' returns 'Access Denied!'.\n\n**What is Forwarding?**\nPassing the intercepted operation back to the original object through the `Reflect` API.",
75+
"visualizationType": "memory",
76+
"memoryState": {
77+
"output": [
78+
"hello",
79+
"Access Denied!"
80+
]
81+
},
82+
"code": "console.log(proxy.public); // hello",
83+
"highlightOffset": [
84+
0,
85+
1
86+
]
87+
}
88+
]
89+
},
90+
"quiz": {
91+
"question": "Which of the following is NOT a valid Trap that can be defined in a Proxy handler?",
92+
"options": [
93+
"get (property read)",
94+
"set (property write)",
95+
"construct (new call)",
96+
"Direct access to private (#) fields"
97+
],
98+
"correctIndex": 3,
99+
"explanation": "A Proxy can only intercept public operations on an object (Public Interception).\nIt cannot directly intervene with internal Private (#) fields or internal slots."
100+
},
101+
"misconceptions": [
102+
{
103+
"wrong": "A Proxy copies the original object and works on the copy",
104+
"correct": "No — it holds a reference to the original and acts as a middleman.",
105+
"why": "The Proxy itself stores no data.\nIt's a wrapper that either forwards requests to the original (Target) through the handler, or blocks them."
106+
}
107+
],
108+
"keyTakeaway": "The 'magic' of modern libraries like Vue 3's reactivity system is built on Proxy."
109+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
{
2+
"lessonId": "js-9-2",
3+
"title": "Generators",
4+
"concept": "A generator is a special function that can pause execution in the middle (Yield) and resume it later (Resume).",
5+
"content": {
6+
"code": "function* counter() {\n console.log('Start!');\n yield 1; // Pause execution (return value 1)\n console.log('Resumed!');\n yield 2; // Pause execution (return value 2)\n console.log('Done!');\n}\n\n// Calling the function doesn't run it — it returns an Iterator (control object)\nconst gen = counter();\n\nconsole.log(gen.next()); // { value: 1, done: false }\nconsole.log(gen.next()); // { value: 2, done: false }\nconsole.log(gen.next()); // { value: undefined, done: true }",
7+
"steps": [
8+
{
9+
"title": "Defining a generator function",
10+
"explanation": "The `function*` syntax marks this as a generator function.\n\n**What is a generator?**\nA regular function runs to completion once called (Run-to-completion), but a generator can pause partway through and resume later.",
11+
"visualizationType": "memory",
12+
"memoryState": {
13+
"stack": [
14+
{
15+
"name": "counter",
16+
"value": "GeneratorFunction"
17+
}
18+
]
19+
},
20+
"code": "function* counter() {",
21+
"highlightOffset": [
22+
0,
23+
1,
24+
2,
25+
3,
26+
4,
27+
5,
28+
6
29+
]
30+
},
31+
{
32+
"title": "Creating the generator object",
33+
"explanation": "Calling `counter()` does not run the function body — instead, it returns a **Generator object (Iterator)**.\nThis object gives you control over when the function executes.",
34+
"keyInsight": "Calling a generator function = creating an Iterator, not running the function",
35+
"visualizationType": "memory",
36+
"memoryState": {
37+
"stack": [
38+
{
39+
"name": "gen",
40+
"value": "Generator { status: 'suspended' }"
41+
}
42+
]
43+
},
44+
"code": "const gen = counter();"
45+
},
46+
{
47+
"title": "First next() call",
48+
"explanation": "Calling `gen.next()` starts the function for the first time.\n'Start!' is logged, then execution pauses at `yield 1`.\n\n**What is Yield?**\nA keyword that pauses execution — handing control and a value back to the caller while keeping the execution context intact.",
49+
"visualizationType": "memory",
50+
"memoryState": {
51+
"output": [
52+
"시작!",
53+
"{ value: 1, done: false }"
54+
],
55+
"heap": [
56+
{
57+
"address": "0xGen",
58+
"content": "Generator { suspended at line 3 }"
59+
}
60+
]
61+
},
62+
"code": "console.log(gen.next()); // { value: 1, done: false }",
63+
"highlightOffset": [
64+
0,
65+
-10,
66+
-9
67+
]
68+
},
69+
{
70+
"title": "Second next() call",
71+
"explanation": "Calling `gen.next()` again resumes from just after `yield 1`.\n'Resumed!' is logged, then execution pauses again at `yield 2`.",
72+
"visualizationType": "memory",
73+
"memoryState": {
74+
"output": [
75+
"재개!",
76+
"{ value: 2, done: false }"
77+
],
78+
"heap": [
79+
{
80+
"address": "0xGen",
81+
"content": "Generator { suspended at line 5 }"
82+
}
83+
]
84+
},
85+
"code": "console.log(gen.next()); // { value: 2, done: false }",
86+
"highlightOffset": [
87+
0,
88+
-9,
89+
-8
90+
]
91+
},
92+
{
93+
"title": "Third next() call — completion",
94+
"explanation": "The final `gen.next()` call.\n'Done!' is logged, and since there are no more yields, `done: true` is returned.",
95+
"keyInsight": "done: true = the generator has finished executing completely",
96+
"visualizationType": "memory",
97+
"memoryState": {
98+
"output": [
99+
"끝!",
100+
"{ value: undefined, done: true }"
101+
],
102+
"heap": [
103+
{
104+
"address": "0xGen",
105+
"content": "Generator { closed }"
106+
}
107+
]
108+
},
109+
"code": "console.log(gen.next()); // { value: undefined, done: true }",
110+
"highlightOffset": [
111+
0,
112+
-8
113+
]
114+
}
115+
]
116+
},
117+
"quiz": {
118+
"question": "What signal indicates that a generator function has fully finished executing?",
119+
"options": [
120+
"value: null",
121+
"done: true",
122+
"status: finished",
123+
"yield: undefined"
124+
],
125+
"correctIndex": 1,
126+
"explanation": "When the IteratorResult object `{ value: ..., done: true }` is returned, it means there is no more code left to run."
127+
},
128+
"misconceptions": [
129+
{
130+
"wrong": "Generators run concurrently like multiple threads",
131+
"correct": "No — they still run on a single thread.",
132+
"why": "Generators only pass execution control back and forth (Cooperative Multitasking) — they don't run simultaneously.\nOnly one thing executes at a time."
133+
}
134+
],
135+
"keyTakeaway": "Because you can pause and resume function execution, generators are useful for writing asynchronous code that reads like synchronous code (e.g., Redux-Saga)."
136+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
{
2+
"lessonId": "js-9-3",
3+
"title": "WeakMap and Preventing Memory Leaks",
4+
"concept": "WeakMap uses 'weak references' to objects, allowing the garbage collector to reclaim them and preventing memory leaks.",
5+
"content": {
6+
"code": "let user = { name: 'Alice' };\n\n// 1. Regular Map (strong reference)\nconst strongMap = new Map();\nstrongMap.set(user, 'Data');\n\n// 2. WeakMap (weak reference)\nconst weakMap = new WeakMap();\nweakMap.set(user, 'Secret');\n\n// Deleting the user object (breaking the reference)\nuser = null;\n\n// Result:\n// strongMap still holds Alice (memory not freed)\n// weakMap releases Alice (collected by GC)",
7+
"steps": [
8+
{
9+
"title": "Creating the object",
10+
"explanation": "The `{ name: 'Alice' }` object is created on the Heap, and the `user` variable points to it.",
11+
"visualizationType": "memory",
12+
"memoryState": {
13+
"heap": [
14+
{
15+
"address": "0xAlice",
16+
"content": "{ name: 'Alice' }",
17+
"refCount": 1
18+
}
19+
]
20+
},
21+
"code": "let user = { name: 'Alice' };"
22+
},
23+
{
24+
"title": "Strong Map: strong reference",
25+
"explanation": "Alice is registered as a key in a regular `Map`.\nThis is a **Strong Reference**.\n\n**What is a strong reference?**\nIt tells the GC: \"I'm watching this — don't ever remove it!\"\nSo even if the `user` variable goes away, Alice stays in memory as long as the Map is alive.",
26+
"visualizationType": "memory",
27+
"memoryState": {
28+
"heap": [
29+
{
30+
"address": "0xAlice",
31+
"content": "{ name: 'Alice' }",
32+
"refCount": 2,
33+
"note": "Ref by user & strongMap"
34+
}
35+
]
36+
},
37+
"code": "strongMap.set(user, 'Data');",
38+
"highlightOffset": [
39+
-1,
40+
0
41+
]
42+
},
43+
{
44+
"title": "WeakMap: weak reference",
45+
"explanation": "Alice is also registered in a `WeakMap`.\nBut this uses a **Weak Reference**.\n\n**What is a weak reference?**\nIt says: \"I can see this object, but don't keep it alive just for me.\"\nIf no other variable references Alice, the WeakMap's reference is ignored and GC can collect it.",
46+
"visualizationType": "memory",
47+
"memoryState": {
48+
"note": "weakMap added ref, but it doesn't count for GC"
49+
},
50+
"code": "weakMap.set(user, 'Secret');",
51+
"highlightOffset": [
52+
-1,
53+
0
54+
]
55+
},
56+
{
57+
"title": "Breaking the reference (user = null)",
58+
"explanation": "Setting `user = null` severs the variable's connection to Alice.\nNow only the Maps hold a reference to her.\n\n* **strongMap**: Holds on tightly — Alice stays in memory.\n(Leak)\n* **weakMap**: Weak reference only — GC can collect Alice.",
59+
"visualizationType": "memory",
60+
"memoryState": {
61+
"heap": [
62+
{
63+
"address": "0xAlice",
64+
"content": "{ name: 'Alice' }",
65+
"refCount": 1,
66+
"note": "Only strongMap holds it. If strongMap dies, Alice dies."
67+
}
68+
]
69+
},
70+
"code": "user = null;"
71+
}
72+
]
73+
},
74+
"quiz": {
75+
"question": "Which of the following CANNOT be used as a key in a WeakMap?",
76+
"options": [
77+
"A DOM element (document.body)",
78+
"An empty object ({})",
79+
"A string (\"hello\")",
80+
"A function (function() {})"
81+
],
82+
"correctIndex": 2,
83+
"explanation": "WeakMap keys must be reference types (objects).\nPrimitive types like strings and numbers are not managed by GC (Reference Counting), so they cannot serve as weak keys."
84+
},
85+
"misconceptions": [
86+
{
87+
"wrong": "You can check the size of a WeakMap with WeakMap.size",
88+
"correct": "You cannot — there is no size property.",
89+
"why": "Because it's impossible to predict when GC will run and collect objects (non-deterministic), counting how many entries remain is not feasible."
90+
}
91+
],
92+
"keyTakeaway": "Use WeakMap when storing cache or temporary data — it prevents memory leaks by letting GC clean up automatically."
93+
}

0 commit comments

Comments
 (0)