annotate core-javascript/solution-2.rst @ 213:0ea90a1819c2 default tip

Custom theming
author Radomir Dopieralski <radomir.dopieralski@allegro.pl>
date Wed, 27 Jun 2012 16:35:54 +0200
parents 6c98b9680b2a
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
108
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
1 Solution two
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
2 ============
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
3
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
4 Here's the code we are studying. The first task is make a loop that
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
5 does the assignments.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
6
145
58e4f484903f Fix errors caused by mv in previous commit.
Jonathan Fine <jfine@pytex.org>
parents: 108
diff changeset
7 .. literalinclude:: /core-javascript-work/exercise-2.js
108
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
8 :language: javascript
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
9
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
10
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
11 Making a loop
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
12 -------------
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
13
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
14 As previously hinted, we use item access rather than attribute access.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
15 The problem with attribute access is that the name of the key is
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
16 hard-coded and we want it to vary during the loop.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
17
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
18 Here's the solution. There's a bit of overhead in setting up the
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
19 loop, but the body of the loop is straightforward.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
20
145
58e4f484903f Fix errors caused by mv in previous commit.
Jonathan Fine <jfine@pytex.org>
parents: 108
diff changeset
21 .. literalinclude:: /core-javascript-work/solution-2-a.js
108
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
22 :language: javascript
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
23
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
24
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
25 Factory function
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
26 ----------------
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
27
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
28 The second task is to write a factory function that takes the list of
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
29 keys as a parameter.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
30
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
31 This is a common refactoring pattern, and so is worth learning well.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
32 First we give the code, and then the explanation.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
33
145
58e4f484903f Fix errors caused by mv in previous commit.
Jonathan Fine <jfine@pytex.org>
parents: 108
diff changeset
34 .. literalinclude:: /core-javascript-work/solution-2-b.js
108
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
35 :language: javascript
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
36
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
37
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
38 Here's what we've done. We created a wrapper function, with *keys* as
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
39 its only parameter. This will be our factory function. We've placed
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
40 the original function into the body of the wrapper, and return it (as
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
41 the value of the wrapper function). Finally, we clean up by removing
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
42 the *keys* constant from the inner function.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
43
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
44 There, it's done! When the factory function executes it returns an
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
45 instance of the inner function for which *keys* is the argument we
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
46 supplied to the factory.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
47
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
48
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
49 A prototype class
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
50 -----------------
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
51
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
52 The third task is to write a Fields class that has a copy_attributes
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
53 method.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
54
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
55 Here's a function prototype based solution. It relies on the user of
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
56 the class supplying the *new* operator to create the new instance (and
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
57 chaos results if the user forgets).
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
58
145
58e4f484903f Fix errors caused by mv in previous commit.
Jonathan Fine <jfine@pytex.org>
parents: 108
diff changeset
59 .. literalinclude:: /core-javascript-work/solution-2-c.js
108
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
60 :language: javascript
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
61
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
62 A minor point is the trailing sequence of right curly braces. Two are
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
63 followed by a semicolon, but the middle one is not. Why? What
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
64 happens if we put a semicolon there?
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
65
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
66
146
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
67 A SimpleClass solution
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
68 ----------------------
108
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
69
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
70 Here's another solution to the third task, which does not require the
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
71 user to supply a *new* operator when creating instances. Instead it
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
72 uses a factory function, which we call *Class* , that creates an
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
73 instance constructor function from a prototype object.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
74
145
58e4f484903f Fix errors caused by mv in previous commit.
Jonathan Fine <jfine@pytex.org>
parents: 108
diff changeset
75 .. literalinclude:: /core-javascript-work/solution-2-d.js
108
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
76 :language: javascript
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
77
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
78
146
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
79 Exercise: write test
108
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
80 --------------------
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
81
146
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
82 Here's an exercise. Write a JavaScript file that tests this solution.
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
83
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
84
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
85 Exercise: bound method class
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
86 ----------------------------
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
87
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
88
108
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
89 Recall that this-based instance methods are somewhat fragile. In
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
90 other words, code like this will fail (and make unwanted changes to
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
91 the global object):
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
92
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
93 .. code-block:: javascript
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
94
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
95 var instance = MyClass(arg1, arg2);
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
96
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
97 var fn = instance.method;
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
98 element.onclick(fn);
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
99
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
100 Let's say that a class *has bound methods* if we can safely pass
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
101 around instance methods. In other words, we want *instance.method* to
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
102 have no dependence on the value of *this*.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
103
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
104 We can achieve this by using a different class factory function.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
105
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
106 .. code-block:: javascript
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
107
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
108 var myclass = {} // The prototype object.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
109 // Add methods to myclass.
109725c066f4 Add solution to exercise 2.
jf3243
parents:
diff changeset
110 var MyClass = BoundMethodClass(myclass);
146
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
111
6c98b9680b2a Revisions to solution-2.rst and its solutiion-2-d.js component.
Jonathan Fine <jfine@pytex.org>
parents: 145
diff changeset
112 The exercise is to create (and test) a BoundMethodClass factory.