@@ -30,6 +30,7 @@ <h1>JavaScript Garden</h1>
30
30
< ul >
31
31
< li > < a href ="#intro "> Intro</ a > </ li >
32
32
< li > < a href ="#objects "> Objects</ a > </ li >
33
+ < li > < a href ="#prototype "> The Prototype</ a > </ li >
33
34
< li > < a href ="#hasownproperty "> < code > hasOwnProperty</ code > </ a > </ li >
34
35
< li > < a href ="#forinloop "> The For In Loop</ a > </ li >
35
36
< li > < a href ="#arrays "> Arrays</ a > </ li >
@@ -89,14 +90,13 @@ <h1>JavaScript Garden</h1>
89
90
90
91
</ section > < section > < header > < h3 > Objects as a Datatype</ h3 > </ header >
91
92
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 >
96
97
97
98
< 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
100
100
101
101
var test = {
102
102
delete: function() {}
@@ -109,6 +109,92 @@ <h1>JavaScript Garden</h1>
109
109
the parser). But you can simply work around this by using a string with the
110
110
value of < code > 'delete'</ code > instead of the plain literal.</ p > </ section > </ article >
111
111
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
+
112
198
< article > < section > < header > < h2 id ="hasownproperty "> < code > hasOwnProperty</ code > < a href ="#intro "> ^</ a > </ h2 > </ header >
113
199
< p > If you want to check whether a < code > Object</ code > has a property defined on < strong > itself</ strong > (and
114
200
not just somewhere on the < a href ="#prototype "> prototype chain</ a > , you have to use the
@@ -150,9 +236,9 @@ <h1>JavaScript Garden</h1>
150
236
chain when iterating over the properties of an < code > Object</ code > .</ p >
151
237
152
238
< 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 >
156
242
</ blockquote >
157
243
158
244
< 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>
161
247
nature of traversing the complete prototype chain, the < code > for in</ code > loop can get
162
248
incredible slow for complex inheritance structures.</ p >
163
249
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
165
251
var foo = {moo: 2};
166
252
for(var i in foo) {
167
253
console.log(i);
@@ -1108,7 +1194,8 @@ <h1>JavaScript Garden</h1>
1108
1194
10 == '10'; // Strings gets converted to Number
1109
1195
10 == '+10 '; // More string madness
1110
1196
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
1112
1199
1113
1200
// These are false
1114
1201
10 == 010;
@@ -1127,8 +1214,7 @@ <h1>JavaScript Garden</h1>
1127
1214
1128
1215
< pre > < code > new Number(10) === 10; // False, Object and Number
1129
1216
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
1132
1218
</ code > </ pre >
1133
1219
1134
1220
< 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>
1199
1285
1200
1286
// foo is not interpreted as an object key, but as a label
1201
1287
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
1203
1289
1204
1290
} // Another semicolon gets inserted here
1205
1291
</ code > </ pre >
@@ -1252,7 +1338,7 @@ <h1>JavaScript Garden</h1>
1252
1338
< code > setTimeout</ code > won't raise an error, but simply do nothing.</ p >
1253
1339
</ blockquote >
1254
1340
1255
- < h4 > Stacking calls with < code > setInterval</ code > </ h4 >
1341
+ </ section > < section > < header > < h3 > Stacking calls with < code > setInterval</ code > </ h3 > </ header >
1256
1342
1257
1343
< p > While < code > setTimeout</ code > only runs the function once, < code > setInterval</ code > - as the name
1258
1344
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>
1273
1359
it. Now when < code > foo</ code > has finished, there will already be < strong > ten</ strong > further calls to
1274
1360
waiting to for execution.</ p >
1275
1361
1276
- < h4 > Dealing with possible blocking code</ h4 >
1362
+ </ section > < section > < header > < h3 > Dealing with possible blocking code</ h3 > </ header >
1277
1363
1278
1364
< p > The easiest as well as most controllable solution is to use < code > setTimeout</ code > within
1279
1365
the function itself.</ p >
@@ -1289,7 +1375,7 @@ <h4>Dealing with possible blocking code</h4>
1289
1375
stacking of calls from happening and it gives additional control since < code > foo</ code > can
1290
1376
now decide on its own whether it wants to run again or not.</ p >
1291
1377
1292
- < h4 > Manually clearing timeouts</ h4 >
1378
+ </ section > < section > < header > < h3 > Manually clearing timeouts</ h3 > </ header >
1293
1379
1294
1380
< p > In order to remove set timeouts and intervals one has to use < code > clearTimeout</ code > and
1295
1381
< code > clearInterval</ code > and supply to them the ID that was return by the corresponding
@@ -1299,7 +1385,7 @@ <h4>Manually clearing timeouts</h4>
1299
1385
clearTimeout(id);
1300
1386
</ code > </ pre >
1301
1387
1302
- < h4 > Clearing all timeouts</ h4 >
1388
+ </ section > < section > < header > < h3 > Clearing all timeouts</ h3 > </ header >
1303
1389
1304
1390
< p > There's no built in way to clear all timeouts or intervals, one has to use brute
1305
1391
force.</ p >
@@ -1313,7 +1399,7 @@ <h4>Clearing all timeouts</h4>
1313
1399
< p > Note that there might be even higher IDs then in the above example, so make sure
1314
1400
to keep track of your timeout IDs, so you can avoid code such as the above.</ p >
1315
1401
1316
- < h4 > Things to avoid at all costs</ h4 >
1402
+ </ section > < section > < header > < h3 > Things to avoid at all costs</ h3 > </ header >
1317
1403
1318
1404
< p > < code > setTimeout</ code > and < code > setInterval</ code > can also take a string as their first parameter.
1319
1405
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>
1347
1433
}, 1000)
1348
1434
</ code > </ pre >
1349
1435
1350
- < h4 > Best Practices</ h4 >
1436
+ </ section > < section > < header > < h3 > Best Practices</ h3 > </ header >
1351
1437
1352
1438
< p > < strong > Never</ strong > use a string as the parameter of < code > setTimeout</ code > or < code > setInterval</ code > its a
1353
1439
sign of < strong > really</ strong > bad code, if you need to supply arguments to the function,
0 commit comments