Skip to content

Commit 48917f2

Browse files
committed
Update
1 parent 149d491 commit 48917f2

File tree

1 file changed

+106
-20
lines changed

1 file changed

+106
-20
lines changed

index.html

Lines changed: 106 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ <h1>JavaScript Garden</h1>
3030
<ul>
3131
<li><a href="#intro">Intro</a></li>
3232
<li><a href="#objects">Objects</a></li>
33+
<li><a href="#prototype">The Prototype</a></li>
3334
<li><a href="#hasownproperty"><code>hasOwnProperty</code></a></li>
3435
<li><a href="#forinloop">The For In Loop</a></li>
3536
<li><a href="#arrays">Arrays</a></li>
@@ -89,14 +90,13 @@ <h1>JavaScript Garden</h1>
8990

9091
</section><section><header><h3>Objects as a Datatype</h3></header>
9192

92-
<p>Objects can also <strong>act</strong> like a <a href="http://en.wikipedia.org/wiki/Hashmap"><em>Hashmap</em></a> in JavaScript by simply mapping <em>keys</em> to
93-
<em>values</em>. Using the curly brace notation <code>{}</code> one can create a new plain object,
94-
which inherits from <code>Object.prototype</code> and has no <a href="#hasownproperty">own
95-
properties</a>.</p>
93+
<p>Objects can also <strong>act</strong> like a <a href="http://en.wikipedia.org/wiki/Hashmap"><em>Hashmap</em></a> in JavaScript by simply mapping
94+
<em>keys</em> to <em>values</em>. Using the curly brace notation <code>{}</code> one can create a new
95+
plain object, which inherits from <code>Object.prototype</code> and has no
96+
<a href="#hasownproperty">own properties</a>.</p>
9697

9798
<pre><code>var foo = {}; // a new empty object
98-
var bar = {test: 12}; // a new object which has one property called 'test'
99-
// which value is 12
99+
var bar = {test: 12}; // a new object with a property
100100

101101
var test = {
102102
delete: function() {}
@@ -109,6 +109,92 @@ <h1>JavaScript Garden</h1>
109109
the parser). But you can simply work around this by using a string with the
110110
value of <code>'delete'</code> instead of the plain literal.</p></section></article>
111111

112+
<article><section><header><h2 id="prototype">The Prototype <a href="#intro">^</a></h2></header>
113+
<p>JavaScript does not feature the classical inheritance model, instead it uses a
114+
<em>prototypal</em> one. This might at first seem like a limitation, but it's not. a
115+
<em>prototypal</em> inheritance model is in fact more powerful than the classical
116+
one, for example you can emulate the classical model with it, but you can't do it
117+
the other way around.</p>
118+
119+
<p>Due to the fact that JavaScript is practically the only language in that's both in
120+
widespread <strong>and</strong> uses prototypical inheritance, it takes some time to adjust
121+
to the differences between the two models. Inheritance in JavaScript is done by
122+
using <em>prototype chains</em>.</p>
123+
124+
<pre><code>function Foo() {
125+
this.value = 42;
126+
}
127+
Foo.prototype = {
128+
method: function() {
129+
}
130+
};
131+
132+
function Bar() {
133+
}
134+
135+
// Set Bar's prototype to the prototype object of Foo
136+
Bar.prototype = Foo.prototype;
137+
138+
var test = new Bar() // create a new bar instance
139+
</code></pre>
140+
141+
<p>The above <code>test</code> object will inherit from both <code>Bar.prototype</code> and
142+
<code>Foo.prototype</code>, so it will have access to the function <code>method</code> that was defined
143+
on <code>Foo</code>, but it will not have access to the value property of a <code>Foo</code> instance
144+
since <code>Foo</code> itself never gets called. </p>
145+
146+
<blockquote>
147+
<p><strong>Note:</strong> Don't use <code>Bar.property = Foo;</code> this will <strong>not</strong> point to <code>Foo</code> its
148+
prototype (therefore <code>method</code> is not on the prototype chain), but rather to the
149+
function object <code>Foo</code>, so the chain will go over <code>Function.prototype</code> in this
150+
case.</p>
151+
</blockquote>
152+
153+
</section><section><header><h3>Property Lookup</h3></header>
154+
155+
<p>If you try to access a property of an <code>Object</code>, JavaScript will traverse the
156+
prototype chain <strong>upwards</strong> until it finds a property with the specified name.
157+
When it reaches the top of the chain - namely <code>Object.prototype</code> - and still
158+
hasn't found the property it will return the value <code>undefined</code>.</p>
159+
160+
<pre><code>// Prototype chain in the example above
161+
Object.prototype: {toString: ... /* etc. */};
162+
Foo.prototype: {method: ...};
163+
Bar.prototype: Foo.prototype
164+
Bar.method()
165+
</code></pre>
166+
167+
<p>You can actually assign <strong>any</strong> <code>object</code> to the <code>prototype</code> property, so consider
168+
the following.</p>
169+
170+
<pre><code>Bar.prototype = new Foo();
171+
var boo = new Bar();
172+
173+
// Resulting prototype chain
174+
Object.prototype: {toString: ... /* etc. */};
175+
Foo.prototype: {method: ...};
176+
[Foo Instance]: {value: 42};
177+
Bar.prototype: [Foo Instance]
178+
Bar.method()
179+
</code></pre>
180+
181+
<p>Now <code>Bar.prototype</code> points to an <strong>instance</strong> of <code>Foo</code>, which of course is just
182+
another object, but this time has the <code>value</code> property defined on it. And since
183+
<code>Foo</code> itself has a prototype, the chain continues with that one afterwards.</p>
184+
185+
<p>As a result of this, the lookup time for properties that are high up the chain
186+
can have a negative impact on performance critical code. Access to non existent
187+
properties will always traverse the full chain and when
188+
<a href="#the-for-in-loop">iterating</a> over the properties of an <code>Object</code> <strong>every</strong>
189+
property that's on the <code>prototype</code> chain will get enumerated.</p>
190+
191+
</section><section><header><h3>Best Practices</h3></header>
192+
193+
<p>Make sure to that you understand the prototypical inheritance model completely,
194+
otherwise you will end up with unexpected, seemingly surprising results. Also,
195+
watch the prototype chains of your objects, remember that they can have a big
196+
impact on performance when not used correctly.</p></section></article>
197+
112198
<article><section><header><h2 id="hasownproperty"><code>hasOwnProperty</code> <a href="#intro">^</a></h2></header>
113199
<p>If you want to check whether a <code>Object</code> has a property defined on <strong>itself</strong> (and
114200
not just somewhere on the <a href="#prototype">prototype chain</a>, you have to use the
@@ -150,9 +236,9 @@ <h1>JavaScript Garden</h1>
150236
chain when iterating over the properties of an <code>Object</code>.</p>
151237

152238
<blockquote>
153-
<p><strong>Note:</strong> The <code>for in</code> loop it will <strong>not</strong> iterate over any properties that have
154-
their <code>enumerable</code> attribute set to <code>false</code>, for example the <code>length</code> property of
155-
an <code>Array</code>.</p>
239+
<p><strong>Note:</strong> The <code>for in</code> loop it will <strong>not</strong> iterate over any properties that
240+
have their <code>enumerable</code> attribute set to <code>false</code>, for example the <code>length</code>
241+
property of an <code>Array</code>.</p>
156242
</blockquote>
157243

158244
<p>Since you cannot change the behavior of the <code>for in</code> loop itself, you have to
@@ -161,7 +247,7 @@ <h1>JavaScript Garden</h1>
161247
nature of traversing the complete prototype chain, the <code>for in</code> loop can get
162248
incredible slow for complex inheritance structures.</p>
163249

164-
<pre><code>Object.prototype.bar = 1; // poisoning the Object.prototype, NEVER do this
250+
<pre><code>Object.prototype.bar = 1; // poisoning the Object.prototype
165251
var foo = {moo: 2};
166252
for(var i in foo) {
167253
console.log(i);
@@ -1108,7 +1194,8 @@ <h1>JavaScript Garden</h1>
11081194
10 == '10'; // Strings gets converted to Number
11091195
10 == '+10 '; // More string madness
11101196
10 == '010'; // And more
1111-
isNaN(null) == false; // null converts to 0, which of cours is not NaN
1197+
isNaN(null) == false; // null converts to 0
1198+
// which of course is not NaN
11121199

11131200
// These are false
11141201
10 == 010;
@@ -1127,8 +1214,7 @@ <h1>JavaScript Garden</h1>
11271214

11281215
<pre><code>new Number(10) === 10; // False, Object and Number
11291216
Number(10) === 10; // True, Number and Number
1130-
new Number(10) + 0 === 10; // True
1131-
// The former is now being converted to a Number
1217+
new Number(10) + 0 === 10; // True, due to implicit conversion
11321218
</code></pre>
11331219

11341220
<p>As you can see above, using the built in type like <code>Number</code> as a constructor,
@@ -1199,7 +1285,7 @@ <h1>JavaScript Garden</h1>
11991285

12001286
// foo is not interpreted as an object key, but as a label
12011287
foo: 1 // JavaScript supports single expression evaluation
1202-
// So 1 evaluates to 1, and yet again does not raise any error
1288+
// So 1 evaluates to 1 and no error is being raised
12031289

12041290
} // Another semicolon gets inserted here
12051291
</code></pre>
@@ -1252,7 +1338,7 @@ <h1>JavaScript Garden</h1>
12521338
<code>setTimeout</code> won't raise an error, but simply do nothing.</p>
12531339
</blockquote>
12541340

1255-
<h4>Stacking calls with <code>setInterval</code></h4>
1341+
</section><section><header><h3>Stacking calls with <code>setInterval</code></h3></header>
12561342

12571343
<p>While <code>setTimeout</code> only runs the function once, <code>setInterval</code> - as the name
12581344
suggests - will execute the function <strong>every</strong> <code>X</code> milliseconds. But its use is
@@ -1273,7 +1359,7 @@ <h4>Stacking calls with <code>setInterval</code></h4>
12731359
it. Now when <code>foo</code> has finished, there will already be <strong>ten</strong> further calls to
12741360
waiting to for execution.</p>
12751361

1276-
<h4>Dealing with possible blocking code</h4>
1362+
</section><section><header><h3>Dealing with possible blocking code</h3></header>
12771363

12781364
<p>The easiest as well as most controllable solution is to use <code>setTimeout</code> within
12791365
the function itself.</p>
@@ -1289,7 +1375,7 @@ <h4>Dealing with possible blocking code</h4>
12891375
stacking of calls from happening and it gives additional control since <code>foo</code> can
12901376
now decide on its own whether it wants to run again or not.</p>
12911377

1292-
<h4>Manually clearing timeouts</h4>
1378+
</section><section><header><h3>Manually clearing timeouts</h3></header>
12931379

12941380
<p>In order to remove set timeouts and intervals one has to use <code>clearTimeout</code> and
12951381
<code>clearInterval</code> and supply to them the ID that was return by the corresponding
@@ -1299,7 +1385,7 @@ <h4>Manually clearing timeouts</h4>
12991385
clearTimeout(id);
13001386
</code></pre>
13011387

1302-
<h4>Clearing all timeouts</h4>
1388+
</section><section><header><h3>Clearing all timeouts</h3></header>
13031389

13041390
<p>There's no built in way to clear all timeouts or intervals, one has to use brute
13051391
force.</p>
@@ -1313,7 +1399,7 @@ <h4>Clearing all timeouts</h4>
13131399
<p>Note that there might be even higher IDs then in the above example, so make sure
13141400
to keep track of your timeout IDs, so you can avoid code such as the above.</p>
13151401

1316-
<h4>Things to avoid at all costs</h4>
1402+
</section><section><header><h3>Things to avoid at all costs</h3></header>
13171403

13181404
<p><code>setTimeout</code> and <code>setInterval</code> can also take a string as their first parameter.
13191405
Do <strong>not</strong> make use of this feature, since it internally makes use of <code>eval</code>.</p>
@@ -1347,7 +1433,7 @@ <h4>Things to avoid at all costs</h4>
13471433
}, 1000)
13481434
</code></pre>
13491435

1350-
<h4>Best Practices</h4>
1436+
</section><section><header><h3>Best Practices</h3></header>
13511437

13521438
<p><strong>Never</strong> use a string as the parameter of <code>setTimeout</code> or <code>setInterval</code> its a
13531439
sign of <strong>really</strong> bad code, if you need to supply arguments to the function,

0 commit comments

Comments
 (0)