Skip to content

Commit 5355cca

Browse files
committed
add arrow function examples
1 parent d088982 commit 5355cca

1 file changed

Lines changed: 197 additions & 0 deletions

File tree

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
<html>
2+
<head>
3+
<title>Arrow Functions vs Regular Functions</title>
4+
<link href="css/style.css" rel="stylesheet">
5+
<style>
6+
body { max-width: 800px; margin: 2em auto; padding: 0 1em; font-family: sans-serif; }
7+
section { border: 1px solid #ccc; padding: 1em; margin: 1em 0; border-radius: 6px; }
8+
button { padding: 0.5em 1em; margin: 0.25em 0.25em 0.25em 0; }
9+
pre { background: #f5f5f5; padding: 0.75em; overflow-x: auto; }
10+
.out { background: #111; color: #0f0; padding: 0.5em; min-height: 1.5em; font-family: monospace; white-space: pre-wrap; }
11+
h2 { margin-bottom: 0.25em; }
12+
.note { color: #555; font-size: 0.9em; }
13+
</style>
14+
</head>
15+
<body>
16+
17+
<h1>Arrow Functions vs Regular Functions</h1>
18+
<p>Open the console and click the buttons. Each section highlights one behavioral difference between
19+
<code>function</code> declarations and arrow functions (<code>=&gt;</code>).</p>
20+
21+
<!-- ========================================================= -->
22+
<section>
23+
<h2>1. <code>this</code> binding</h2>
24+
<p class="note">Regular functions get their own <code>this</code> based on how they are called.
25+
Arrow functions capture <code>this</code> from the enclosing scope.</p>
26+
<pre>const obj = {
27+
name: "Widget",
28+
regular: function () { return this; }, // `this` === obj
29+
arrow: () =&gt; this, // `this` === outer scope (window)
30+
};</pre>
31+
<button id="thisRegular">Call regular</button>
32+
<button id="thisArrow">Call arrow</button>
33+
<div class="out" id="thisOut"></div>
34+
</section>
35+
36+
<!-- ========================================================= -->
37+
<section>
38+
<h2>2. <code>this</code> inside a callback</h2>
39+
<p class="note">A classic bug: a regular function passed as a callback loses its <code>this</code>.
40+
An arrow function inherits it from the surrounding method, so it just works.</p>
41+
<pre>class Counter {
42+
constructor() { this.count = 0; }
43+
44+
startBroken() {
45+
setInterval(function () { this.count++; }, 500); // `this` is window, not the Counter
46+
}
47+
48+
startFixed() {
49+
setInterval(() =&gt; { this.count++; }, 500); // `this` is the Counter
50+
}
51+
}</pre>
52+
<button id="startBroken">Start broken (regular fn)</button>
53+
<button id="startFixed">Start fixed (arrow fn)</button>
54+
<button id="stopTimers">Stop</button>
55+
<div class="out" id="counterOut"></div>
56+
</section>
57+
58+
<!-- ========================================================= -->
59+
<section>
60+
<h2>3. <code>arguments</code> object</h2>
61+
<p class="note">Regular functions have a special <code>arguments</code> variable. Arrow functions
62+
do not — referencing it either errors or falls through to an outer scope.</p>
63+
<pre>function regular() { return arguments.length; }
64+
const arrow = () =&gt; arguments.length; // ReferenceError (in a module)</pre>
65+
<button id="argsRegular">regular(1, 2, 3)</button>
66+
<button id="argsArrow">arrow(1, 2, 3)</button>
67+
<div class="out" id="argsOut"></div>
68+
</section>
69+
70+
<!-- ========================================================= -->
71+
<section>
72+
<h2>4. Constructors</h2>
73+
<p class="note">Regular functions can be called with <code>new</code>. Arrow functions cannot.</p>
74+
<pre>function Person(name) { this.name = name; }
75+
const PersonArrow = (name) =&gt; { this.name = name; };
76+
77+
new Person("Ada"); // works
78+
new PersonArrow("Ada"); // TypeError: PersonArrow is not a constructor</pre>
79+
<button id="newRegular">new Person("Ada")</button>
80+
<button id="newArrow">new PersonArrow("Ada")</button>
81+
<div class="out" id="newOut"></div>
82+
</section>
83+
84+
<!-- ========================================================= -->
85+
<section>
86+
<h2>5. Hoisting</h2>
87+
<p class="note">Function declarations are hoisted — you can call them before the line that defines them.
88+
Arrow functions are assigned to variables, so they follow <code>const</code>/<code>let</code> rules.</p>
89+
<pre>hoisted(); // works
90+
notHoisted(); // ReferenceError
91+
92+
function hoisted() { return "I'm up here early"; }
93+
const notHoisted = () =&gt; "I'm only available after this line";</pre>
94+
<button id="hoistBtn">Run hoisting demo</button>
95+
<div class="out" id="hoistOut"></div>
96+
</section>
97+
98+
<script>
99+
function log(id, msg) {
100+
const el = document.getElementById(id);
101+
el.textContent += msg + "\n";
102+
console.log(msg);
103+
}
104+
function clear(id) { document.getElementById(id).textContent = ""; }
105+
106+
// 1. `this` binding ------------------------------------------------
107+
const obj = {
108+
name: "Widget",
109+
regular: function () { return this; },
110+
arrow: () => this,
111+
};
112+
document.getElementById("thisRegular").onclick = () => {
113+
clear("thisOut");
114+
const t = obj.regular();
115+
log("thisOut", "regular() -> this.name = " + (t && t.name));
116+
log("thisOut", "this === obj? " + (t === obj));
117+
};
118+
document.getElementById("thisArrow").onclick = () => {
119+
clear("thisOut");
120+
const t = obj.arrow();
121+
log("thisOut", "arrow() -> this === window? " + (t === window));
122+
log("thisOut", "this.name = " + (t && t.name)); // undefined
123+
};
124+
125+
// 2. `this` in a callback ------------------------------------------
126+
class Counter {
127+
constructor() { this.count = 0; this.timer = null; }
128+
startBroken() {
129+
this.stop();
130+
this.timer = setInterval(function () {
131+
// `this` here is window, so this.count is undefined
132+
log("counterOut", "broken: this.count = " + this.count);
133+
}, 500);
134+
}
135+
startFixed() {
136+
this.stop();
137+
this.count = 0;
138+
this.timer = setInterval(() => {
139+
this.count++;
140+
log("counterOut", "fixed: this.count = " + this.count);
141+
}, 500);
142+
}
143+
stop() { if (this.timer) { clearInterval(this.timer); this.timer = null; } }
144+
}
145+
const counter = new Counter();
146+
document.getElementById("startBroken").onclick = () => { clear("counterOut"); counter.startBroken(); };
147+
document.getElementById("startFixed").onclick = () => { clear("counterOut"); counter.startFixed(); };
148+
document.getElementById("stopTimers").onclick = () => counter.stop();
149+
150+
// 3. `arguments` ---------------------------------------------------
151+
function regularArgs() { return Array.from(arguments); }
152+
const arrowArgs = () => {
153+
try { return Array.from(arguments); }
154+
catch (e) { return "Error: " + e.message; }
155+
};
156+
document.getElementById("argsRegular").onclick = () => {
157+
clear("argsOut");
158+
log("argsOut", "regularArgs(1, 2, 3) = " + JSON.stringify(regularArgs(1, 2, 3)));
159+
};
160+
document.getElementById("argsArrow").onclick = () => {
161+
clear("argsOut");
162+
const result = arrowArgs(1, 2, 3);
163+
log("argsOut", "arrowArgs(1, 2, 3) = " + JSON.stringify(result));
164+
log("argsOut", "(Arrow functions inherit `arguments` from the enclosing scope,");
165+
log("argsOut", " so use rest params instead: const f = (...args) => args;)");
166+
};
167+
168+
// 4. Constructors --------------------------------------------------
169+
function Person(name) { this.name = name; }
170+
const PersonArrow = (name) => { this.name = name; };
171+
document.getElementById("newRegular").onclick = () => {
172+
clear("newOut");
173+
const p = new Person("Ada");
174+
log("newOut", "new Person('Ada') -> " + JSON.stringify(p));
175+
};
176+
document.getElementById("newArrow").onclick = () => {
177+
clear("newOut");
178+
try { new PersonArrow("Ada"); }
179+
catch (e) { log("newOut", "TypeError: " + e.message); }
180+
};
181+
182+
// 5. Hoisting ------------------------------------------------------
183+
document.getElementById("hoistBtn").onclick = () => {
184+
clear("hoistOut");
185+
// Inside this handler we simulate top-level ordering by using eval-free tricks.
186+
// Declarations are hoisted within this function body too.
187+
log("hoistOut", "hoisted() returns: " + hoisted());
188+
try { log("hoistOut", "notHoisted() returns: " + notHoisted()); }
189+
catch (e) { log("hoistOut", "notHoisted() threw: " + e.message); }
190+
191+
function hoisted() { return "I'm up here early"; }
192+
const notHoisted = () => "I'm only available after this line";
193+
};
194+
</script>
195+
196+
</body>
197+
</html>

0 commit comments

Comments
 (0)