Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<com:TContent ID="body" >
2
<h1 id="6501">Introduction to Javascript</h1>
3
This guide is based on the <a href="http://www.sergiopereira.com/articles/advjs.html">
4
Quick guide to somewhat advanced JavaScript tour of some OO features</a> by Sergio Pereira.
5
 
6
<h2 id="6502">Hey, I didn't know you could do that</h2>
7
<p id="820693" class="block-content">
8
    If you are a web developer and come from the same place I do, you have probably
9
    used quite a bit of Javascript in your web pages, mostly as UI glue.
10
</p>
11
<p id="820694" class="block-content">
12
 
13
    Until recently, I knew that Javascript had more OO capabilities than I was employing,
14
    but I did not feel like I needed to use it. As the browsers started to support a more
15
    standardized featureset of Javascript and the DOM, it became viable to write more
16
    complex and functional code to run on the client. That helped giving birth to the
17
    AJAX phenomena.
18
</p>
19
<p id="820695" class="block-content">
20
    As we all start to learn what it takes to write our cool, AJAX applications, we begin
21
    to notice that the Javascript we used to know was really just the tip of the iceberg.
22
    We now see Javascript being used beyond simple UI chores like input validation and frivolous
23
    tasks. The client code now is far more advanced and layered, much like a real desktop
24
    application or a client-server thick client. We see class libraries, object models,
25
    hierarchies, patterns, and many other things we got used to seeing only in our server
26
    side code.
27
</p>
28
<p id="820696" class="block-content">
29
    In many ways we can say that suddenly the bar was put much higher than before. It takes
30
    a heck lot more proficiency to write applications for the new Web and we need to improve
31
    our Javascript skills to get there.
32
    If you try to use many of the existing javascript libraries out there, like
33
    <a href="http://prototype.conio.net/">Prototype.js</a>,
34
    <a href="http://script.aculo.us/">Scriptaculous</a>,
35
    <a href="http://moofx.mad4milk.net/">moo.fx</a>,
36
    <a href="http://bennolan.com/behaviour/">Behaviour</a>,
37
    <a href="http://developer.yahoo.net/yui/">YUI</a>,
38
    etc you'll eventually find yourself reading the JS code. Maybe because you want
39
    to learn how they do it, or because you're curious, or more often because that's the
40
    only way to figure out how to use it, since documentation does not seem to be highly
41
    regarded with most of these libraries. Whatever the case may be, you'll face some
42
    kung-fu techniques that will be foreign and scary if you haven't seen anything like
43
    that before.
44
</p>
45
 
46
<p id="820697" class="block-content">
47
    The purpose of this article is precisely explaining the types of constructs that
48
    many of us are not familiar with yet.
49
</p>
50
 
51
 
52
<h2 id="6503">JSON (JavaScript Object Notation)</h2>
53
<p id="820698" class="block-content">
54
    JavaScript Object Notation (<a href="http://www.json.org/">JSON</a>,) is one of the new
55
    buzzwords popping up around the AJAX theme. JSON, simply put, is a way of
56
    declaring an object in Javascript. Let's see an example right away and note
57
    how simple it is.
58
</p>
59
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820233">
60
var myPet = { color: 'black', leg_count: 4, communicate: function(repeatCount){
61
for(i=0;i&lt;repeatCount;i++) alert('Woof!');} };
62
</com:TTextHighlighter>
63
 
64
<p id="820699" class="block-content">
65
    Let's just add little bit of formatting so it looks more like how we usually find out there:
66
</p>
67
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820234">
68
var myPet =
69
{
70
    color: 'black',
71
    legCount: 4,
72
    communicate: function(repeatCount)
73
    {
74
        for(i=0;i&lt;repeatCount;i++)
75
            alert('Woof!');
76
    }
77
};
78
</com:TTextHighlighter>
79
<p id="820700" class="block-content">
80
    Here we created a reference to an object with two properties (<tt>color</tt>
81
    and <tt>legCount</tt>) and a method (<tt>communicate</tt>.)
82
    It's not hard to figure out that the object's properties and methods
83
    are defined as a comma delimited list. Each of the members is introduced by name, followed
84
    by a colon and then the definition. In the case of the properties it is easy, just the value
85
    of the property. The methods are created by assigning an anonymous function, which we will
86
    explain better down the line.
87
    After the object is created and assigned to the variable <tt>myPet</tt>,
88
    we can use it like this:
89
</p>
90
 
91
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820235">
92
alert('my pet is ' + myPet.color);
93
alert('my pet has ' + myPet.legCount + ' legs');
94
//if you are a dog, bark three times:
95
myPet.communicate(3);
96
</com:TTextHighlighter>
97
<p id="820701" class="block-content">
98
    You'll see JSON used pretty much everywhere in JS these days, as arguments to functions,
99
    as return values, as server responses (in strings,) etc.
100
</p>
101
 
102
<h2 id="6504">What do you mean? A function is an object too?</h2>
103
<p id="820702" class="block-content">
104
    This might be unusual to developers that never thought about that, but in JS a function is
105
    also an object. You can pass a function around as an argument to another function just like
106
    you can pass a string, for example. This is extensively used and very handy.
107
</p>
108
 
109
<p id="820703" class="block-content">
110
    Take a look at this example. We will pass functions to another function that will use them.
111
</p>
112
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820236">
113
var myDog =
114
{
115
    bark: function()
116
    {
117
        alert('Woof!');
118
    }
119
};
120
 
121
var myCat =
122
{
123
    meow: function()
124
    {
125
        alert('I am a lazy cat. I will not meow for you.');
126
    }
127
};
128
 
129
function annoyThePet(petFunction)
130
{
131
    //let's see what the pet can do
132
    petFunction();
133
}
134
 
135
//annoy the dog:
136
annoyThePet(myDog.bark);
137
//annoy the cat:
138
annoyThePet(myCat.meow);
139
</com:TTextHighlighter>
140
<p id="820704" class="block-content">
141
    Note that we pass myDog.bark and myCat.meow without appending parenthesis
142
    <tt>"()"</tt> to them. If we did that we would not be passing
143
    the function, rather we would be calling the method and passing the return value,
144
    <tt>undefined</tt> in both cases here.
145
</p>
146
 
147
<p id="820705" class="block-content">
148
    If you want to make my lazy cat start barking, you can easily do this:
149
</p>
150
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820237">
151
myCat.meow = myDog.bark;
152
myCat.meow(); //alerts 'Woof!'
153
</com:TTextHighlighter>
154
 
155
<h2 id="6505">Arrays, items, and object members</h2>
156
<p id="820706" class="block-content">
157
    The following two lines in JS do the same thing.
158
</p>
159
 
160
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820238">
161
var a = new Array();
162
var b = [];
163
</com:TTextHighlighter>
164
<p id="820707" class="block-content">
165
    As I'm sure you already know, you can access individual items in an array
166
    by using the square brackets:
167
</p>
168
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820239">
169
var a = ['first', 'second', 'third'];
170
var v1 = a[0];
171
var v2 = a[1];
172
var v3 = a[2];
173
</com:TTextHighlighter>
174
<p id="820708" class="block-content">
175
 
176
    But you are not limited to numeric indices. You can access any member of a JS
177
    object by using its name, in a string. The following example creates an empty
178
    object, and adds some members by name.
179
</p>
180
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820240">
181
var obj = {}; //new, empty object
182
obj['member_1'] = 'this is the member value';
183
obj['flag_2'] = false;
184
obj['some_function'] = function(){ /* do something */};
185
</com:TTextHighlighter>
186
<p id="820709" class="block-content">
187
    The above code has identical effect as the following:
188
</p>
189
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820241">
190
var obj =
191
{
192
    member_1:'this is the member value',
193
    flag_2: false,
194
    some_function: function(){ /* do something */}
195
};
196
</com:TTextHighlighter>
197
 
198
<p id="820710" class="block-content">
199
    In many ways, the idea of objects and associative arrays (hashes) in JS are not
200
    distiguishable. The following two lines do the same thing too.
201
</p>
202
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820242">
203
obj.some_function();
204
obj['some_function']();
205
</com:TTextHighlighter>
206
 
207
 
208
<h2 id="6506">Enough about objects, may I have a class now?</h2>
209
<p id="820711" class="block-content">
210
 
211
    The great power of object oriented programming languages derive from the use
212
    of classes. I don't think I would have guessed how classes are defined in JS
213
    using only my previous experience with other languages. Judge for yourself.
214
</p>
215
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820243">
216
//defining a new class called Pet
217
var Pet = function(petName, age)
218
{
219
    this.name = petName;
220
    this.age = age;
221
};
222
 
223
//let's create an object of the Pet class
224
var famousDog = new Pet('Santa\'s Little Helper', 15);
225
alert('This pet is called ' + famousDog.name);
226
</com:TTextHighlighter>
227
<p id="820712" class="block-content">
228
    Let's see how we add a method to our <tt>Pet</tt> class. We will be using the
229
    <tt>prototype</tt> property that all classes have. The <tt>prototype</tt>
230
    property is an object that contains all the members that any object of the class will have.
231
    Even the default JS classes, like <tt>String</tt>, <tt>Number</tt>,
232
    and <tt>Date</tt> have a <tt>prototype</tt> object that we
233
    can add methods and properties to and make any object of that class automatically gain this new member.
234
</p>
235
 
236
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820244">
237
Pet.prototype.communicate = function()
238
{
239
    alert('I do not know what I should say, but my name is ' + this.name);
240
};
241
</com:TTextHighlighter>
242
<p id="820713" class="block-content">
243
    That's when a library like <a href="http://www.sergiopereira.com/articles/prototype.js.html">prototype.js</a> comes in
244
    handy. If we are using prototype.js, we can make our code look cleaner (at least in my opinion.)
245
</p>
246
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820245">
247
var Pet = Class.create();
248
Pet.prototype =
249
{
250
    //our 'constructor'
251
    initialize: function(petName, age)
252
    {
253
        this.name = petName;
254
        this.age = age;
255
    },
256
 
257
    communicate: function()
258
    {
259
        alert('I do not know what I should say, but my name is ' + this.name);
260
    }
261
};
262
</com:TTextHighlighter>
263
 
264
<h2 id="6507">Functions as arguments, an interesting pattern</h2>
265
<p id="820714" class="block-content">
266
    If you have never worked with languages that support closures
267
     you may find the following idiom too funky.
268
</p>
269
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820246">
270
var myArray = ['first', 'second', 'third'];
271
myArray.each( function(item, index)
272
{
273
    alert('The item in the position #' + index + ' is:' + item);
274
});
275
</com:TTextHighlighter>
276
<p id="820715" class="block-content">
277
 
278
    Whoa! Let's explain what is going on here before you decide I've gone too
279
    far and navigate to a better article than this one.
280
</p>
281
<p id="820716" class="block-content">
282
    First of all, in the above example we are using the prototype.js library, which
283
    adds the each function to the Array class. The each function accepts one
284
    argument that is a function object. This function, in turn, will be called once
285
    for each item in the array, passing two arguments when called, the item and the index
286
    for the current item. Let's call this function our iterator function.
287
    We could have also written the code like this.
288
</p>
289
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820247">
290
function myIterator(item, index)
291
{
292
    alert('The item in the position #' + index + ' is:' + item);
293
}
294
 
295
var myArray = ['first', 'second', 'third'];
296
myArray.each( myIterator );
297
</com:TTextHighlighter>
298
<p id="820717" class="block-content">
299
    But then we would not be doing like all the cool kids in school, right?
300
    More seriously, though, this last format is simpler to understand but causes
301
    us to jump around in the code looking for the myIterator function. It's nice
302
    to have the logic of the iterator function right there in the same place
303
    it's called. Also, in this case, we will not need the iterator function anywhere
304
    else in our code, so we can transform it into an anonymous function without penalty.
305
</p>
306
 
307
<h2 id="6508">This is <tt>this</tt> but sometimes <tt>this</tt> is also that</h2>
308
<p id="820718" class="block-content">
309
 
310
    One of the most common troubles we have with JS when we start writing our code
311
    it the use of the <tt>this</tt> keyword. It could be a real
312
    tripwire.
313
</p>
314
<p id="820719" class="block-content">
315
    As we mentioned before, a function is also an object in JS, and sometimes we
316
    do not notice that we are passing a function around.
317
</p>
318
<p id="820720" class="block-content">
319
    Take this code snippet as an example.
320
</p>
321
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820248">
322
function buttonClicked()
323
{
324
    alert('button ' + this.id + ' was clicked');
325
}
326
 
327
var myButton = document.getElementById('someButtonID');
328
var myButton2 = document.getElementById('someOtherButtonID');
329
myButton.onclick = buttonClicked;
330
myButton2.onclick = buttonClicked;
331
</com:TTextHighlighter>
332
<p id="820721" class="block-content">
333
    Because the buttonClicked function is defined outside any object we may tend to
334
    think the <tt>this</tt> keyword will contain a reference to
335
    the <tt>window</tt> or <tt>document</tt>
336
    object (assuming this code is in the middle of an HTML page viewed in a browser.)
337
</p>
338
 
339
<p id="820722" class="block-content">
340
    But when we run this code we see that it works as intended and displays the <tt>id</tt> of
341
    the clicked button. What happened here is that we made the onclick method of each button contain the
342
    <tt>buttonClicked</tt> object reference, replacing whatever was there before. Now
343
    whenever the button is clicked, the browser will execute something similar to the following line.
344
</p>
345
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820249">
346
myButton.onclick();
347
</com:TTextHighlighter>
348
<p id="820723" class="block-content">
349
 
350
    That isn't so confusing afterall, is it? But see what happens you start having other
351
    objects to deal with and you want to act on these object upon events like the button's click.
352
</p>
353
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820250">
354
var myHelper =
355
{
356
    formFields: [ ],
357
    emptyAllFields: function()
358
    {
359
        for(i=0; i < this.formFields.length; i++)
360
        {
361
            var elementID = this.formFields[i];
362
            var field = document.getElementById(elementID);
363
            field.value = '';
364
        }
365
    }
366
};
367
 
368
//tell which form fields we want to work with
369
myHelper.formFields.push('txtName');
370
myHelper.formFields.push('txtEmail');
371
myHelper.formFields.push('txtAddress');
372
 
373
//clearing the text boxes:
374
myHelper.emptyAllFields();
375
 
376
var clearButton = document.getElementById('btnClear');
377
clearButton.onclick = myHelper.emptyAllFields;
378
</com:TTextHighlighter>
379
<p id="820724" class="block-content">
380
    So you think, nice, now I can click the Clear button on my page and those three text boxes
381
    will be emptied. Then you try clicking the button only to get a runtime error. The error
382
    will be related to (guess what?) the <tt>this</tt> keyword.
383
    The problem is that <tt>this.formFields</tt> is not defined if
384
    <tt>this</tt> contains a referece to the button, which is
385
    precisely what's happening. One quick solution would be to rewrite our last line of code.
386
</p>
387
 
388
<com:TTextHighlighter Language="javascript" CssClass="source block-content" id="code_820251">
389
clearButton.onclick = function()
390
{
391
    myHelper.emptyAllFields();
392
};
393
</com:TTextHighlighter>
394
<p id="820725" class="block-content">
395
    That way we create a brand new function that calls our helper method within the helper object's context.
396
</p>
397
<div class="last-modified">$Id: Scripts.page 1650 2007-01-24 06:55:32Z wei $</div></com:TContent>