Вы находитесь на странице: 1из 288

32.988.02-018.

1
004.43
39

39  JavaScript. 68 JS.

.: , 2013. 288 .: . ( ).

ISBN 978-5-496-00524-1
JavaScript . , ,
JavaScript
.
68
JavaScript,
. ,
, ,
JavaScript.
12+ ( 12 .
29 2010 . 436-.)
32.988.02-018.1
004.43
Addison-Wesley Longman.
.
.
, , , . ,
,
, .
ISBN 978-0321812186 .
ISBN 978-5-496-00524-1
Pearson Education, Inc.
, 2013
, , 2013

. . . . . . . . . . . . . . . . . . . . . . . . . . 9
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
JavaScript ECMAScript. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
-. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 14

. . . . . . . . . . . . . . . . . . . . . . . . 15
. . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.
JavaScript . . . . . . . . . . . . . . . . . . . . . 19
1. , JavaScript . . . . . .
2. . . . . . . . . . . . . . . . . . .
3. . .. .. .. ..
4.  ,
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
5.  ==
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6. 
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
7. 
16- . . . . . . . . . . . . . . . .

20
28
32
40
42
46
55

2. . . . . . . . . 61
8. 
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9. . . . . . . . . . . . . . . . . . . . .
10. with . .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
11. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
12. . .. .. .. .. .. .. .. .. .. .. .. ..
13. 
-
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
14. 
,
- . . . . . . . . . . . . . . . . . . . . . . . . . .
15.  ,
-
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
16. 
eval. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17.  eval
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

61
65
67
72
76

79

83

88
91
93

3. . . . . . . . . . . . . . 96

18.  ,
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 96
19. 
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .100
20.  call
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .105
21.  apply
. . . . . . . . . . . . . . . . . . . . . . . . . . .107
22.  arguments
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 110
23. arguments. . . . . . .112
24. 
arguments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .115
25.  bind
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .117
26. bind . . . . .120
27. 
, . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .122


28. toString . . . . . . .124
29. 
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .127

4. . . . . . . . . . . . . . . 130
30. 
prototype, getPrototypeOf __proto__ . .. .. .. .. .. .. .. .. .. .. .. 131
31. 
Object.getPrototypeOf, __proto__. . . . . . . . . . . . .135
32. __proto__. . . . .136
33.  ,
new. .. .. .. .. .. .. .. 138
34. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 142
35. 
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .144
36. 
-. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 147
37. this. . . . . . . . . . . . . . . . . . .150
38. 
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .154
39. . .. 159
40. . . . . . . . . .161
41. . .. .. .. .. .. .. .. 164
42. 
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .166

5. . . . . . . . . . . . . . . . . 169
43. 
. . . . . . . . . . . . . . .169
44.  null
. . . . . . . . .173
45.  hasOwnProperty
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 176
46.  ,
. .. .. .. .. .. .. 182
47. 
Object.prototype . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 186
48. . 188
49. 
for, for...in. . . . .194


50. 
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 196
51. 
Array , . . . . .202
52.  ,
Array . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 205

6. API . . . . . . . . . . 207
53. . .. .. .. .. .. .. .. 207
54. undefined . . .210
55.  , ,
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 216
56. . .. .. .. .. .. .. .. .. 222
57. 
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 226
58. . . . . . . . . . . . . . . . . . . . . . . .232
59. . . . . . . .237
60. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .242

7. . . . . . . . . . . . . . . . . . . . . 246
61. -. . . . . . .247
62. 

. . . . . . . . . . . . . . . . . . . . . . . . . . .252
63. 
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .257
64. . . . . . . . . .262
65. . . . . . . . . . . .267
66. 
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .272
67. 
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .278
68. 
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 282

, JavaScript
1995 , ,
Java,
, ,
Netscape , .
, ( , ), ,
,
JavaScript . ,
,
, ,
.
,
, ,
,
, JavaScript

.
, , . (,

).

(monkey-patching),

,
(
,
spackle).
,
, , JavaScript,

.
,
: Prototype Ruby, MochiKit Python,
Dojo Java, TIBET Smalltalk. JavaScript jQuery (JavaScript
), ,
2007 , .
-
JavaScript-,
,
.

JavaScript ,

, ,
-.

10

JavaScript ( ) ,
, ,
ECMAScript , ,
,

. JavaScript
. , JavaScript
.
,
( ),
, .
,

, JavaScript (, !). ,
, , JavaScript
, . , ,
, ,

, .
,
. ,
, JavaScript, .
, , .
,
2006 , Mozilla Ecma.
,
,
. !
(Brendan Eich)

11


, ,
, ,
.
,
, ,

. , ,
, JavaScript.

12

JavaScript. , ,
JavaScript
. , JavaScript,
(Douglas Crockford), JavaScript: The
Good Parts (Marijn Haverbeke)
Eloquent JavaScript. ,
JavaScript
,
.

JavaScript ECMAScript
.
,
JavaScript. ,
, , ECMAScript. ,
: , Ecma
International,
JavaScript. ,
ECMA
(European Computer Manufacturers Association) Ecma
International, , (ECMAScript),
.
, ECMAScript,
,
Ecma. , JavaScript , ,
, - . .


ECMAScript,
JavaScript. ES5
ECMAScript.

-
JavaScript, -. JavaScript ,

13

- ,
. ,
, Node.js, JavaScript
. -, JavaScript,
-.
, -
,
,
, API- -.

JavaScript ,

. ,
ECMAScript JavaScript
. 7, JavaScript .
JavaScript- .

JavaScript,
. ,
JavaScript

ECMAScript.

14

JavaScript (Brendan Eich).


JavaScript
Mozilla.
,
, -.
(Ben) cowboy (Alman),
(Erik Arvidsson),
(Mathias Bynens), (Tim) creationix (Caswell),
(Michaeljohn) inimino (Clement),
(Angus Croll), (Andrew
Dupont), (Ariya Hidayat),
(Steven Levithan), (Pan Thomakos),
(Jeff Walden) (Juriy) kangax
(Zaytsev). ,
ECMAScript, , Edition5, - (Allen Wirfs-Brock).
Mozilla Developer Network

API- .

. (John Resig)
, ,
.

15

(Blake Kaplan) (Patrick Walton)


.
(Brian Anderson),
(Norbert Lindenberg), (Sam Tobin-Hochstadt), (Rick
Waldron) (Patrick Walton).
Pearson. (Olivia Basegio),
(Audrey Doyle), (Trina MacDonald),
(Scott Meyers) (Chris Zahn)
,
.
.
, . ,
(Erik Arvidsson),
(Rebecca Murphey), (Rick Waldron)
(Richard Worth),
.
.
, .
. ,
, (Andy Denmark),
(Rick Waldron) (Travis Winfrey)
.

Java Beach -.
.
.

16


, .
,
. (, .)

2006,
.

. , , , ,

. ,

,
.
, ,
, (Lisa
Silveria), .

17


Mozilla Research. ,
, ( )
- .
Ecma TC39, , JavaScript.

18

1.

JavaScript

JavaScript .
, Java,
, (
, , ), JavaScript ,
. ,
,

.
JavaScript
, .

JavaScript,
.

19

1. JavaScript

,
JavaScript

, JavaScript
. Java -, JavaScript
Java
-. JavaScript
1997
,
ECMAScript. JavaScript,
ECMAScript.
ECMAScript ( ES3), 1999,
JavaScript.

ES5 (Edition5), 2009. ES5
, ,
,
, .
ES5 ,
, ES5,
.

20

,
, JavaScript. , JavaScript-

const, ECMAScript
-
. ,
const .
,
const, :

1. , JavaScript
const PI = 3.141592653589793;
PI = "!";
PI; // 3.141592653589793

const var:
const PI = 3.141592653589793;
PI = "!";
PI; // "!"

-
JavaScript, -
. , JavaScript -
JavaScript .

-, -
.
JavaScript - .

,
.

JavaScript. JavaScript .
JavaScript.

, .

, , .
,

21

1. JavaScript

,
. ,
const
, ,
-, .
ES5
.
JavaScript,
,
.
, , ,
.

:
"use strict";

,

:
function f(x) {
"use strict";
// ...
}

22

,
:

, ES3

.
, JavaScript, :
, -

1. , JavaScript

.
ES5, ,
ES5:
function f(x) {
"use strict";
var arguments = []; // :
// arguments
// ...
}

arguments
, ,
, .

, ES5.
,
ES5.

, "use strict"
, ,
,

. ,
:
// file1.js
"use strict";
function f() {
// ...
}
// ...

,
:
// file2.js
//
function g() {

23

1. JavaScript
var arguments = [];
// ...
}
// ...

?
file1.js,
:
// file1.js
"use strict";
function f() {
// ...
}
// ...
// file2.js
//
function f() {
var arguments = []; // :
// arguments
// ...
}
// ...

file2.js,
:
// file2.js
//
function g() {
var arguments = [];
// ...
}
// ...
// file1.js
"use strict";
function f() { //
//
// ...
}

24

// ...

1. , JavaScript


, ,
,
.
, , , .

, , , , ,

.

, , ,
, .
, - (Immediately Invoked Function Expression, IIFE).

13,
,
- .

:
//
(function() {
// file1.js
"use strict";
function f() {
// ...
}
// ...
})();

25

1. JavaScript
(function() {
// file2.js
//
function f() {
var arguments = [];
// ...
}
// ...
})();


, (
)
.
. , var function
(
8).
,
,
.
,
,
.
, .

, ,
, , ,

.
, ,

26

1. , JavaScript

. ,
IIFE,
IIFE ,
,
, :
(function() {
"use strict";
function f() {
// ...
}
// ...
})();

,
, . ,
,
,
, . , ,
,
.

, JavaScript .
,
JavaScript ,
.
, , , .
, - .

1. JavaScript

, JavaScript
.
typeof,
:
typeof 17;

// ""

typeof 98.6; // ""


typeof -2.1; // ""

JavaScript
, 64- , IEEE754,
doubles (
). , , ,
53.
9007199254740992 (253) 9007199254740992
(253)
.
, JavaScript
.
,
:
0.1 * 1.9

// 0.19

-99 + 100; // 1
21 - 12.3; // 8.7

28

2.5 / 5;

// 0.5

21 % 8;

// 5

.

, 32--

2.

. (,
32- .) , ,
OR ():
8 | 1; // 9


. , JavaScript 8 1 ,
32-
, ,
. 32- 8
:
00000000000000000000000000001000

,
toString:
(8).toString(2); // "1000"

toString , 2 ( ).
,
, .
1 32- :
00000000000000000000000000000001

OR
, (1),
,
:
00000000000000000000000000001001


9. -

29

1. JavaScript

parseInt,
2:
parseInt("1001", 2); // 9

( ,
.)
,
,
, JavaScript
. ,
JavaScript- :
,
,
.
,

,
, .
, : ,
, , .
, , ,
.
,
, :
0.1 + 0.2; // 0.30000000000000004

64- ,
,
.

,
.

30

2.

,
,
. ,
. , ,
, x, y z
:
(x + y) + z = x + (y + z).
:
(0.1 + 0.2) + 0.3; // 0.6000000000000001
0.1 + (0.2 + 0.3); // 0.6

.
, ,
.

, ,
.
, , ,
.
. , ,
,

:
(10 + 20) + 30; // 60
10 + (20 + 30); // 60

, ,
,
253 253.
.

31

1. JavaScript

JavaScript .
JavaScript ,
.
,
32- .
, .

, JavaScript ,
.
:
3 + true; // 4

, true
.

. ,
. JavaScript
,
4!


JavaScript. , ,
null:
"hello"(1); // :
null.x;

32

// :
// 'x' null

3.

, , JavaScript ,
. ,
-, *, / % . +
,
, :
2 + 3; // 5
"hello" + " world"; // "hello world"

?
JavaScript :
"2" + 3; // "23"
2 + "3"; // "23"

, -
. :
1 + 2 + "3"; // "33"

(
),
:
(1 + 2) + "3"; // "33"

:
1 + "2" + 3; // "123"


"123"

,
:
(1 + "2") + 3; // "123"

33

1. JavaScript


, ,
32- ,
2.
(~, &, ^ |)
(<<, >> >>>).

, , ,
:
"17" * 3; // 51
"8" | "1"; // 9

. , null,
, 0;

NaN,
(not a number), IEEE- !
,

. , NaN, .
-, JavaScript IEEE-
, NaN
. NaN :
var x = NaN;
x === NaN; // false

34

, isNaN
,
, -

3.

. (
isNaN , , coercesToNaN ,
NaN.)
, , NaN isNaN:
isNaN(NaN); // true

, NaN, NaN,
NaN:
isNaN("foo");

// true

isNaN(undefined);

// true

isNaN({});

// true

isNaN({ valueOf: "foo" }); // true

, NaN
,
. NaN
JavaScript-,
,
NaN :
var a = NaN;
a !== a;

// true

var b = "foo";
b !== b;

// false

var c = undefined;
c !== c;

// false

var d = {};
d !== d;

// false

var e = { valueOf: "foo" };


e !== e;

// false


:
function isReallyNaN(x) {
return x !== x;
}

35

1. JavaScript


, ,
.

,
, .
,
,
, ,
- . ,
, .
,

, ,
.
.
:
"the Math object: " + Math; // "the Math object:
// [object Math]"
"the JSON object: " + JSON; // "the JSON object:
// [object JSON]"


toString. , :
Math.toString(); // "[object Math]"
JSON.toString(); // "[object JSON]"


,
valueOf.
, :
"J" + { toString: function() { return "S"; } }; // "JS"

36

2 * { valueOf: function() { return 3; } };

// 6

3.

,
+ , . ,
, toString, valueOf, ,
+: ,

,
, !
JavaScript ,
valueOf, toString.
,

:
var obj = {
toString: function() {
return "[object MyObject]";
},
valueOf: function() {
return 17;
}
};
"object: " + obj; // "object: 17"

, valueOf
, ,
Number. toString
valueOf

+
, ,
. ,

, .
valueOf, obj.toString()
,
obj.valueOf().

37

1. JavaScript

. , if, || &&,
, ,
. JavaScript .
JavaScript ,
true. ,
- .
: false , 0 , -0 , "" , NaN
undefined. .
,
.
, , :
function point(x, y) {
if (!x) {
x = 320;
}
if (!y) {
y = 240;
}
return { x: x, y: y };
}

,
0:
point(0, 0); // { x: 320, y: 240 }

typeof:
function point(x, y) {
if (typeof x === "undefined") {
x = 320;

38

3.
if (typeof y === "undefined") {
y = 240;
}
return { x: x, y: y };
}

point 0
undefined:
point();

// { x: 320, y: 240 }

point(0, 0); // { x: 0, y: 0 }


undefined:
if (x === undefined) { ... }


API 54.

, , .
+ .
valueOf
toString.
, valueOf,
toString, ,
valueOf.

typeof undefined,
.

39

1. JavaScript

JavaScript
: , , , null undefined. ( ,
typeof null "object", ECMA-Script
.)
,
,
. String,
:
var s = new String("hello");

, String ,
.
:
s + " world"; // "hello world"


:
s[4]; // "o"

, String
:
typeof "hello"; // "string"
typeof s;

// "object"

,
String :
var s1 = new String("hello");
var s2 = new String("hello");

40

s1 === s2; // false

4. ,

String , .
:
s1 == s2; // false

, .

. JavaScript
:

, ,
. , String
toUpperCase ,
.
:
"hello".toUpperCase(); // "HELLO"

, :
"hello".someProperty = 17;
"hello".someProperty; // undefined


String,
.

, JavaScript
. , , JavaScript , : ,
,

.

.

41

1. JavaScript


, .

.


==

, :
"1.0e0" == { valueOf: function() { return true; } };

, ,
== , -
(. 3),
. "1.0e0"
1,
valueOf
(true) ,
1.

,
- :
var today = new Date();
if (form.month.value == (today.getMonth() + 1) &&
form.day.value == today.getDate()) {
// !
// ...

42

5. ==


, Number
+:
var today = new Date();
if (+form.month.value == (today.getMonth() + 1) &&
+form.day.value == today.getDate()) {
// !
// ...
}

, ,

. :
var today = new Date();
if (+form.month.value === (today.getMonth() + 1) &&
//
+form.day.value === today.getDate()) {
//
// !
// ...
}

,
== === .
, ,
,
.
,
. , ,
.
, .
1.1 -

43

1. JavaScript

==, . ,
null == undefined,
undefined == null.
, .
,
valueOf toString, .
Date,
.
1.1. ==
1

null

undefined

; true

, null

; false

null undefined

undefined

Date

=> , Date

=> (

toString, valueOf )

, -

=> , ,

Date

Date=>

( valueOf,
toString)

=>

5. ==

, ==
.

, . . JavaScript
,
, .
,
, , Date:
var date = new Date("1999/12/31");
date == "1999/12/31"; // false

,
Date , , :
date.toString();
// "Fri Dec 31 1999 00:00:00 GMT-0800 (PST)"

.
== .
, .
,
:
function toYMD(date) {
var y = date.getYear() + 1900, //
//
// 1900
m = date.getMonth() + 1,
//
//
// 0
d = date.getDate();
return y
+ "/" + (m < 10 ? "0" + m : m)
+ "/" + (d < 10 ? "0" + d : d);
}
toYMD(date) === "1999/12/31"; // true

45

1. JavaScript

,
, ==, , ,

.

==
.
, ,
===.
, .

, JavaScript, , . ,
:
function Point(x, y) {
this.x = x || 0
this.y = y || 0
}
Point.prototype.isOrigin = function() {
return this.x === 0 && this.y === 0
}

46

6.

,
,
. ECMAScript
,

JavaScript.
,
, 3 5,
,
.
,
JavaScript ,
.
,
, , .
:
}
.

,
, . ,
:
function square(x) {
var n = +x
return n * n
}
function area(r) { r = +r; return Math.PI * r * r }
function add1(x) { return x + 1 }

:
function area(r) { r = +r return Math.PI * r * r }
//

47

1. JavaScript

:
,
.

, .
:
a = b
(f());

, :
a = b(f());

.
:
a = b
f();

,

:
a = b f();

:
,
,
.
,
.

48

: (, [, +, - /.
, -

6.

, .
,
, .
,
. , ,
, , , .

:
a = b
["r", "g", "b"].forEach(function(key) {
background[key] = foreground[key] / 2;
});

: ,
,
"r", "g" "b".
[ ,
, :
a = b["r", "g", "b"].forEach(function(key) {
background[key] = foreground[key] / 2;
});

,
, JavaScript ,
"b".
+, - / , .
/.
, :
/Error/i.test(str) && fail();

/Error/i.

49

1. JavaScript

, fail. ,
:
a = b
/Error/i.test(str) && fail();


:
a = b / Error / i.test(str) && fail();

, / !
JavaScript-,
, , ,
, .
. ,
:
a = b //
var x //
(f()) //


:
var x //
a = b //
(f()) //

, var

(
12), ,
b , ,
:
var x;

50

a = b(f());

6.

, ,
,
, . ,
, (, [, +, - /. ,

:
a = b

//

var x

//

;(f()) //

var , :
var x

//

a = b

//

;(f()) //

,
,
(.1). ( - 13):
// file1.js
(function() {
// ...
})()
// file2.js
(function() {
// ...
})()

, ,
. , :

51

1. JavaScript
(function() {
// ...
})()
(function() {
// ...
})()

,
:
(function() {
// ...
})()(function() {
// ...
})();

, ,
, ,
.
,

,

(, [, +, - /:
// file1.js
;(function() {
// ...
})()
// file2.js
;(function() {
// ...
})()

,

:
;(function() {

52

// ...

6.
})()
;(function() {
// ...
})()

, ,
.
,
, .
: .
, . :
, JavaScript , , . JavaScript,
-
.
return, -
return .
:
return { };

:
return
{ };

:
return;
{ }
;

, - ,
return,
,

53

1. JavaScript

return ,
. :
yy throw;
yy break continue
;
yy ++ --.
:
a
++
b

++ ,
, - ,
:
a; ++b;

:

for .

,
for .

:
for (var i = 0, total = 1 //
//
i < n
i++) {
total *= i

54

7. 16-


.
:
function infiniteLoop() { while (true) }
//

, :
function infiniteLoop() { while (true); }

},
.
,
.
,
(, [, +, - /.

.
- , return, throw, break continue,
++ --.
for .

16-

55

1. JavaScript

,
, .
.
:
0 1114111, (code point). ,
-
, ASCII.
, , ASCII ,
.
, , ,
.
, UTF-8, UTF-16 UTF-32.

56

,
. ,
216 . UCS-2,
16- ,
.
16- ,
,
(code units). UCS-2
16- ,

. ,
, :
n-
n-16- . .1.1 ,
16- . ,
.

7. 16-
'h'

'e'

'l'

'l'

'o'

0x0068

0x0065

0x006c

0x006c

0x006f

. 1.1. JavaScript-

16- .
Java, JavaScript : JavaScript- 16- .
,
1990-, JavaScript- .
16- ,
,
ASCII
.
,
,
220 .

17 216 .
,
(Basic Multilingual Plane, BMP), 216
. 16 .
, UCS-2 : .
, UTF-16, ,
: 16- ,
2 16
. , ,

57

1. JavaScript

U+1D11E,
119070
UTF-16 0xd834
0xdd1e.
, . ( ,
BMP,
, ,
- .)
.1.2.
,

.
''

' '

'c'

'l'

'e'

'f'

0xd834

0xdd1e

0x0020

0x0063

0x006c

0x0065

0x0066

. 1.2. JavaScript-,

UTF-16
, 16- , UTF-16 :
n
.
, n-
: ,
, .
,
JavaScript 16-
. , length,
charAt charCodeAt,
, .

58

7. 16-

, JavaScript
, ,
UTF-16. :
JavaScript- 16-
.
JavaScript- .
, ,
UTF-16.
.1.2. ,
, JavaScript
, 7:
" clef".length;

// 7

"G clef".length; // 6


, :
" clef".charCodeAt(0);

// 55348 (0xd834)

" clef".charCodeAt(1);

// 56606 (0xdd1e)

" clef".charAt(1) === " "; // false


" clef".charAt(2) === " "; // true


. (".")
:
/^.$/.test("");

// false

/^..$/.test(""); // true

, , ,
:
, length,

59

1. JavaScript


. BMP, ,
.
,
,
.
JavaScript ,
API- . ,
ECMAScript-
; , , URI-:
encodeURI, decodeURI, encodeURIComponent decode
URIComponent. JavaScript
, , -
- ,
, , .

JavaScript- 16- ,
.
216 JavaScript
, .
,
length, charAt, charCodeAt
, ..
,
, .
, ,
, ,
.

2.

.
. .
..., .
, , JavaScript,
, .
. JavaScript

, ,
,
.

JavaScript
.
,

. .

61

2.

, .
,
.
:
.
, ,
,


, .

,
. ,
.

. ,
, . ,
,
,
:
var i, n, sum; //
function averageScore(players) {
sum = 0;
for (i = 0, n = players.length; i < n; i++) {
sum += score(players[i]);
}
return sum / n;
}

62

averageScore , score, ,
-
:

8.
var i, n, sum; // ,
// averageScore!
function score(player) {
sum = 0;
for (i = 0, n = player.levels.length; i < n; i++)
{
sum += player.levels[i].score;
}
return sum;
}

, ,
:
function averageScore(players) {
var i, n, sum;
sum = 0;
for (i = 0, n = players.length; i < n; i++) {
sum += score(players[i]);
}
return sum / n;
}
function score(player) {
var i, n, sum;
sum = 0;
for (i = 0, n = player.levels.length; i < n; i++)
{
sum += player.levels[i].score;
}
return sum;
}

JavaScript ,
this.
window.
:
this.foo; //
foo = "global foo";
this.foo; // "global foo"

63

2.

, :
var foo = "global foo";
this.foo = "changed";
foo; // "changed"

, : -,

var, -, . ,
var ,
,
. ,

,
, .
,
, .
,
,
. , ES5
JSON,
JSON.
, JSON,

:
if (!this.JSON) {
this.JSON = {
parse: ...,
stringify: ...
};

64

9.

JSON,
, ,
. , , :

, .

-,
.

,
.
, , , JavaScript-.

.
.
.
.

, ,
.
, JavaScript

.

65

2.

, ,
.
, ,
- :
function swap(a, i, j) {
temp = a[i]; //
a[i] = a[j];
a[j] = temp;
}


, - var
temp .
temp var:
function swap(a, i, j) {
var temp = a[i];
a[i] = a[j];
a[j] = temp;
}

66

,
. - -,
,
.

. -

( ,
, ),
, , . ,
JavaScript, .

10. with

,
,
.


var.
-, .

10


with

with. , JavaScript
. with :
.
with .
,
:
function status(info) {
var widget = new Widget();
with (widget) {
setBackground("blue");
setForeground("white");
setText("Status: " + info); //
//
show();
}
}

67

2.

with ,
:
function f(x, y) {
with (Math) {
return min(round(x), sqrt(y));
//
}
}

with
.
. , .
,
: -, ,
, , with (
setBackground, round sqrt), -, ,
, ,
( info, x y).

.
, JavaScript : ,
, .
with
, with
. ,
.

68

.2.1 JavaScript-
status, with. ES5
(lexical environment),
(scope chain).

10. with


widget.
info widget.
status. ,
, , ,
.
with ,
.

.status

.info
.widget

._background

.setBackground

.hasOwnProperty

._foreground

.setForeground

.toString

. . .

.setText

.valueOf

.show
widget

. . .

. . .

Object.prototype
Widget.prototype
. 2.1. ( )
status

, ,
, with,

69

2.

? with ,
with .
,
with , . ,
, ,
.

with
. , widget info,
status info, .
, , , ,
info.
, info
- Widget,
status :
status("connecting"); // Status: connecting
Widget.prototype.info = "[[widget info]]";
status("connected");

// Status: [[widget info]]


f, - Math
x y:
Math.x = 0;
Math.y = 0;
f(2, 9); // 0

70

, , - Math x y,
,

. , -

10. with

, ,
.
JavaScript
,
. with
, , , ,
, .
JavaScript -
with.

:
function status(info) {
var w = new Widget();
w.setBackground("blue");
w.setForeground("white");
w.addText("Status: " + info);
w.show();
}

.

w. -
Widget, status
:
status("connecting"); // Status: connecting
Widget.prototype.info = "[[widget info]]";
status("connected");

// Status: connected



:
function f(x, y) {
var min = Math.min, round = Math.round,
sqrt = Math.sqrt;
return min(round(x), sqrt(y));
}

71

2.

, with,
:
Math.x = 0;
Math.y = 0;
f(2, 9); // 2

with.
.

with .

11

,
,
. , , ,
, .
, .
,
. , JavaScript ,
:
function makeSandwich() {
var magicIngredient = "peanut butter";
function make(filling) {
return magicIngredient + " and " + filling;
}
return make("jelly");
}

72

makeSandwich(); // "peanut butter and jelly"

11.

, make
magicIngredient,
makeSandwich.
,
,
, !
- , ,
JavaScript
(.19). ,
:
function sandwichMaker() {
var magicIngredient = "peanut butter";
function make(filling) {
return magicIngredient + " and " + filling;
}
return make;
}
var f = sandwichMaker();
f("jelly");

// "peanut butter and jelly"

f("bananas");

// "peanut butter and bananas"

f("marshmallows"); // "peanut butter and marshmallows"


, make("jelly") , sandwichMaker
make. f
make, f
make. , ,
sandwichMaker , make
magicIngredient.
? ,
JavaScript- , .
,

. ,
, (closures).
make ,

73

2.

: magicIngredient filling.
make
, .

,
.
sandwichMaker:
function sandwichMaker(magicIngredient) {
function make(filling) {
return magicIngredient + " and " + filling;
}
return make;
}
var hamAnd = sandwichMaker("ham");
hamAnd("cheese");

// "ham and cheese"

hamAnd("mustard");

// "ham and mustard"

var turkeyAnd = sandwichMaker("turkey");


turkeyAnd("Swiss");

// "turkey and Swiss"

turkeyAnd("Provolone");

// "turkey and Provolone"

, hamAnd
turkeyAnd.
make, :
magicIngredient "ham",
"turkey".
JavaScript,
.
JavaScript
-:
function sandwichMaker(magicIngredient) {
return function(filling) {
return magicIngredient + " and " + filling;
};
}

74

11.

, -
: ,
,
. -
(. 14).
, , ,
.
, .
, . ,
,
(box) ,
:
function box() {
var val = undefined;
return {
set: function(newVal) { val = newVal; },
get: function() { return val; },
type: function() { return typeof val; }
};
}
var b = box();
b.type(); // "undefined"
b.set(98.6);
b.get();

// 98.6

b.type(); // "number"

,
set (), get
() type ( ). val.
set val,
get type .

75

2.

, .
.
,
, .

12

JavaScript
(lexical scope): foo ,
foo . JavaScript
(block scope):

,
, .
JavaScript
:
function isWinner(player, others) {
var highest = 0;
for (var i = 0, n = others.length; i < n; i++) {
var player = others[i];
if (player.score > highest) {
highest = player.score;
}
}
return player.score > highest;
}

76

for player .

12.

JavaScript , ,
player ,
,
player.
. return player
others,
player.

JavaScript ,
:
. JavaScript
, . , ,
, var.
.2.2.
function f() {
// ...
// ...
{
// ...
var x = /* ... */;
// ...
}
// ...
}

function f() {
var x;
// ...
{
// ...
x = /* ... */;
// ...
}
// ...
}

. 2.2.

.

.
:
function trimSections(header, body, footer) {
for (var i = 0, n = header.length; i < n; i++) {
header[i] = header[i].trim();
}

77

2.
for (var i = 0, n = body.length; i < n; i++) {
body[i] = body[i].trim();
}
for (var i = 0, n = footer.length; i < n; i++) {
footer[i] = footer[i].trim();
}
}

trimSections
( i, n),
. ,
trimSections
:
function trimSections(header, body, footer) {
var i, n;
for (i = 0, n = header.length; i < n; i++) {
header[i] = header[i].trim();
}
for (i = 0, n = body.length; i < n; i++) {
body[i] = body[i].trim();
}
for (i = 0, n = footer.length; i < n; i++) {
footer[i] = footer[i].trim();
}
}


, var
,
,
. ,
, ,
.

78

,
JavaScript , ,
, . trycatch

13. -

caught , catch:
function test() {
var x = "var", result = [];
result.push(x);
try {
throw "exception";
} catch (x) {
x = "catch";
}
result.push(x);
return result;
}
test(); // ["var", "var"]


, .
.
, .

13

(!) :
function wrapElements(a) {
var result = [], i, n;
for (i = 0, n = a.length; i < n; i++) {

79

2.
result[i] = function() { return a[i]; };
}
return result;
}
var wrapped = wrapElements([10, 20, 30, 40, 50]);
var f = wrapped[0];
f(); // ?

, 10,
undefined.

.
,
. wrapElements
: result, i n.
wrapElements .
.
, , ,
, i .
i. i
,
i.
.
,
.

80

, ,
wrapElements,
i, .
i ,

, ,

13. -

, 5
undefined.
, wrapElements
, var
for:
function wrapElements(a) {
var result = [];
for (var i = 0, n = a.length; i < n; i++) {
result[i] = function() { return a[i]; };
}
return result;
}
var wrapped = wrapElements([10, 20, 30, 40, 50]);
var f = wrapped[0];
f(); // undefined

, var .
,
. , i
.

:
function wrapElements(a) {
var result = [];
for (var i = 0, n = a.length; i < n; i++) {
(function() {
var j = i;
result[i] = function() { return a[j]; };
})();
}
return result;
}

, (Immediately Invoked Function Expression,


IIFE), ,

81

2.

JavaScript
.
-
:
function wrapElements(a) {
var result = [];
for (var i = 0, n = a.length; i < n; i++) {
(function(j) {
result[i] = function() { return a[j]; };
})(i);
}
return result;
}

IIFE
,
. -,
break continue,
,

. -,
this
arguments , IIFE .
this arguments
3.

.
, .
- (IIFE).
, IIFE
.

14.

14



,

-

JavaScript- ,
.
:
function double(x) { return x * 2; }


, . :

. ,

double.
-,
. :
var f = function double(x) { return x * 2; };

ECMAScript,
f, double. ,
-,
-:
var f = function(x) { return x * 2; };


- , .
-:
var f = function find(tree, key) {
if (!tree) {
return null;
}

83

2.
if (tree.key === key) {
return tree.value;
}
return find(tree.left, key) ||
find(tree.right, key);
};

, find
.
, - :
find(myTree, "foo"); // : find
//

-
,
:
var f = function(tree, key) {
if (!tree) {
return null;
}
if (tree.key === key) {
return tree.value;
}
return f(tree.left, key) ||
f(tree.right, key);
};

:
function find(tree, key) {
if (!tree) {
return null;
}
if (tree.key === key) {
return tree.value;
}

84

return find(tree.left, key) ||

14.
find(tree.right, key);
}
var f = find;

- .
JavaScript-
Error, - .

- .
, - -
ECMAScript JavaScript-
. ,
ES3, , JavaScript
- ,
, with. , ,
,
Object.prototype. , -
Object.prototype .
:
var constructor = function() { return null; };
var f = function f() {
return constructor();
};
f(); // {} ( ES3)

, null,
, -
Object.prototype.constructor ( - Object). , with,

85

2.

Object.prototype.
Object.prototype ,
-
.
, ES5 .
JavaScript-
. ,

-!
-

null:
var constructor = function() { return null; };
var f = function() {
return constructor();
};
f(); // {} ( , )

, , Object.prototype
,
Object.prototype.
, JavaScript, - . :
var f = function g() { return 17; };
g(); // 17 ( , )

, ,
. , JavaScript-
f g ,
!

86

14.

, -,
null:
var f = function g() { return 17; };
var g = null;

var
g , -, null ,
.
, ,
- - .

-
,
-. :
, (.1). ,
, ,
.

-
Error .
- Object.prototype ES3 JavaScript-.
- JavaScript-.
-
.
,
ES5, .

2.

15


,
-


. , ,
,
.

:
function f() { return "global"; }
function test(x) {
function f() { return "local"; }
var result = [];
if (x) {
result.push(f());
}
result.push(f());
return result;
}
test(true);

// ["local", "local"]

test(false); // ["local"]

f ,
:
function f() { return "global"; }
function test(x) {
var result = [];
if (x) {
function f() { return "local"; }
//
result.push(f());
}
result.push(f());
return result;

88

15.
test(true);

// ?

test(false); // ?

, ,
test ["local", "global"],

["global"], f
if. , JavaScript
, f
test . ,
["local", "local"]
["local"]. JavaScript-
. ! ,
f
, ,
. (
, , with.)
ECMAScript?
, . ES5
; ,
.
ES5

, JavaScript-,
,
, ,

.


, .

-

89

2.

. ,
, .
,
var :
function f() { return "global"; }
function test(x) {
var g = f, result = [];
if (x) {
g = function() { return "local"; }
result.push(g());
}
result.push(g());
return result;
}


( g ):
,
.
.

, ,
-.

var .

90

16. eval

16



eval

JavaScript eval
.
,
. -
eval
.
eval
JavaScript-,
.

:
function test(x) {
eval("var y = x;"); //
return y;
}
test("hello");

// "hello"

, -,
var,
test. var eval. eval

:
var y = "global";
function test(x) {
if (x) {
eval("var y = 'local';"); //

}
return y;
}
test(true);

// "local"

test(false); // "global"

91

2.

, ,

. ,
, ,
.
, , eval,
:
var y = "global";
function test(src) {
eval(src); //
return y;
}
test("var y = 'local';"); // "local"
test("var z = 'local';"); // "global"

: test. ,
eval ,
, - ES5, eval
,
.
eval

:
var y = "global";
function test(src) {
(function() { eval(src); })();
return y;
}
test("var y = 'local';"); // "global"
test("var z = 'local';"); // "global"

92

17. eval

eval,
.
, eval, ,
.

17


eval

eval
.
, ,
. eval
,
. ,
, eval
,
,
, eval.

eval.
eval
eval:
var x = "global";
function test() {
var x = "local";
return eval("x"); // eval
}
test(); // "local"

93

2.


, . ,

. , eval
,
:
var x = "global";
function test() {
var x = "local";
var f = eval;
return f("x"); // eval
}
test(); // "global"

eval
,
ECMAScript. , ,
eval, eval, ,
( ).
eval
(,)
:
(0,eval)(src);

? 0 ,
,
eval. , (0,eval)
, eval,
:
eval.

94

eval
- .

17. eval

, ,
, . 16
,
eval ,
, .
, eval
. ,
, eval , ,

.
eval
. ,
,
eval.

eval , eval
.

eval, .

95

3.

JavaScript,
, .
,
: ,
, .

JavaScript.
,
.

18

96

- , , , ,
.
JavaScript .

18. ,

:
function hello(username) {
return "hello, " + username;
}
hello("Keyser Sze"); // "hello, Keyser Sze"

, : hello username
.
JavaScript ,
, :
var obj = {
hello: function() {
return "hello, " + this.username;
},
username: "Hans Gruber"
};
obj.hello(); // "hello, Hans Gruber"

, hello obj this. ,


this obj, hello
obj.

:
var obj2 = {
hello: obj.hello,
username: "Boo Radley"
};
obj2.hello(); // "hello, Boo Radley"

this,
, ,
. obj.hello()
hello obj
obj. obj2.hello() hello obj2 ( ,
obj.hello), obj2.

97

3.

,
, .
, ,
,
this :
function hello() {
return "hello, " + this.username;
}


:
var obj1 = {
hello: hello,
username: "Gordon Gekko"
};
obj1.hello(); // "hello, Gordon Gekko"
var obj2 = {
hello: hello,
username: "Biff Tannen"
};
obj2.hello(); // "hello, Biff Tannen"

, this, (
):
hello(); // "hello, undefined"

, , ,

username undefined.
- ,
this,
,
,
. , -

98

18. ,

, ES5
this undefined:
function hello() {
"use strict";
return "hello, " + this.username;
}
hello(); // :
// "username",
// (undefined)
//

,
:
undefined .
. , ,

function:
function User(name, passwordHash) {
this.name = name;
this.passwordHash = passwordHash;
}

User new
:
var u = new User("sfalken",
"0ef33ae791068ec64b502d6cb0191387");
u.name; // "sfalken"

, this

. - .

99

3.

,
.

( undefined , ).

- .
new
.

19

; , , .
.

.
,
.
, ,
. (
,
)
, ,
JavaScript.

100

sort . ,

19.

sort ,
:
function compareNumbers(x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
}
[3, 1, 4, 1, 5, 9].sort(compareNumbers); // [1, 1, 3,
//

4, 5, 9]

, ,
.
, ,
:
[3, 1, 4, 1, 5, 9].sort(function(x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
}); // [1, 1, 3, 4, 5, 9]


.


, .
.
, :

101

3.
var names = ["Fred", "Wilma", "Pebbles"];
var upper = [];
for (var i = 0, n = names.length; i < n; i++) {
upper[i] = names[i].toUpperCase();
}
upper; // ["FRED", "WILMA", "PEBBLES"]

map, ( ES5).
,

:
var names = ["Fred", "Wilma", "Pebbles"];
var upper = names.map(function(name) {
return name.toUpperCase();
});
upper; // ["FRED", "WILMA", "PEBBLES"]


, .
. ,
,
:
var aIndex = "a".charCodeAt(0); // 97
var alphabet = "";
for (var i = 0; i < 26; i++) {
alphabet += String.fromCharCode(aIndex + i);
}
alphabet; // "abcdefghijklmnopqrstuvwxyz"

,
:
var digits = "";
for (var i = 0; i < 10; i++) {
digits += i;
}

102

digits; // "0123456789"

19.

- :
var random = "";
for (var i = 0; i < 8; i++) {
random +=
String.fromCharCode(Math.floor(Math.random() * 26)
+ aIndex);
}
random; // "bdwvfrtp" (
//

, ,
.


.
:
function buildString(n, callback) {
var result = "";
for (var i = 0; i < n; i++) {
result += callback(i);
}
return result;
}

, buildString
, :
n ,
.
buildString :
var alphabet = buildString(26, function(i) {
return String.fromCharCode(aIndex + i);
});
alphabet; // "abcdefghijklmnopqrstuvwxyz"
var digits = buildString(10, function(i) { return i; });
digits; // "0123456789"

103

3.
var random = buildString(8, function() {
return
String.fromCharCode(Math.floor(Math.random() * 26)
+ aIndex);
});
random; // "ltvisfjr" (
//


. , ,
, , .
,
,
. ,
, - .
, ,
buildString, , ,
, ,
.
,

, ,
.
.

,
.
.
,
.

20. call

20

call

( ,
this) . ,
this .
, , -.
,
:
obj.temporary = f;

// obj.temporary
// ?

var result = obj.temporary(arg1, arg2, arg3);


delete obj.temporary; // obj.temporary
// ?

.
obj. ,
temporary,

obj. ,
, - . ,

, , (.42).
,
call.
call:
f.call(obj, arg1, arg2, arg3);

,
:
f(arg1, arg2, arg3);

105

3.

, call
-.
call ,
, . 45 , hasOwnProperty
,
. -
hasOwnProperty , :
dict.hasOwnProperty = 1;
dict.hasOwnProperty("foo"); // : 1
//

call hasOwnProperty ,
- :
var hasOwnProperty = {}.hasOwnProperty;
dict.foo = 1;
delete dict.hasOwnProperty;
hasOwnProperty.call(dict, "foo");

// true

hasOwnProperty.call(dict, "hasOwnProperty"); // false

call
.

. , ,
-, forEach:
var table = {
entries: [],
addEntry: function(key, value) {
this.entries.push({ key: key, value: value });
},
forEach: function(f, thisArg) {
var entries = this.entries;
for (var i = 0, n = entries.length; i < n;

106

i++) {

21. apply
var entry = entries[i];
f.call(thisArg, entry.key,
entry.value, i);
}
}
};


f table.forEach
. ,
:
table1.forEach(table2.addEntry, table2);

addEntry table2 (
Table.prototype table1), forEach addEntry
table2, .
, addEntry ,
forEach : , . ()
, addEntry .

call.
call ,
.
call ,

.

21

apply

, - , :

107

3.
average(1, 2, 3);

// 2

average(1);

// 1

average(3, 1, 4, 1, 5, 9, 2, 6, 5); // 4
average(2, 7, 1, 8, 2, 8, 1, 8);

// 4.625

average
, (
):
. ,
average , ,
, :
averageOfArray([1, 2, 3]);

// 2

averageOfArray([1]);

// 1

averageOfArray([3, 1, 4, 1, 5, 9, 2, 6, 5]); // 4
averageOfArray([2, 7, 1, 8, 2, 8, 1, 8]);

// 4.625

, , . , ,
, ,
, .
, :
var scores = getAllScores();

average
?
average(/* ? */);

, apply, call,
. apply
,

.

108

, apply
, this
. average
this, null:

21. apply
var scores = getAllScores();
average.apply(null, scores);

scores , , ,
:
average(scores[0], scores[1], scores[2]);

apply . , buffer append,



( append,
22):
var buffer = {
state: [],
append: function() {
for (var i = 0, n = arguments.length;
i < n; i++) {
this.state.push(arguments[i]);
}
}
};

:
buffer.append("Hello, ");
buffer.append(firstName, " ", lastName, "!");
buffer.append(newline);

apply this,
append :
buffer.append.apply(buffer, getInputStrings());

buffer:
, append
state .

109

3.


apply.

apply.

22

arguments

21 average,

.
?
averageOfArray :
function averageOfArray(a) {
for (var i = 0, sum = 0, n = a.length; i < n; i++)
{
sum += a[i];
}
return sum / n;
}
averageOfArray([2, 7, 1, 8, 2, 8, 1, 8]); // 4.625

averageOfArray
a. averageOfArray,
( , ) .

110

,
- .

22. arguments

, JavaScript
arguments. arguments
, ,
: ,
length . average
, arguments:
function average() {
for (var i = 0, sum = 0, n = arguments.length;
i < n;
i++) {
sum += arguments[i];
}
return sum / n;
}

,
.
:
, apply (.21).

,
.
,
, :
function average() {
return averageOfArray(arguments);
}

apply,
.

111

3.

argu
ments.
apply,
.

23


arguments

arguments , , , , .
, Perl UNIX,
. JavaScript- ,
, shift,

. arguments
Array,
arguments.shift() .
call shift
arguments.

, callMethod,

:
function callMethod(obj, method) {
var shift = [].shift;
shift.call(arguments);
shift.call(arguments);
return obj[method].apply(obj, arguments);

112

23. arguments

:
var obj = {
add: function(x, y) { return x + y; }
};
callMethod(obj, "add", 17, 25);
// : "apply",
// (undefined)

, arguments . ,
arguments.
obj arguments[0], method arguments[1] ,
arguments
shift. , ,
obj["add"], 17[25]!
:
,
17 Number, "25" ( ),
(undefined),
undefined .
,
arguments
. ,
arguments, .
ES5.
arguments. ,
, , arguments:
function strict(x) {
"use strict";
arguments[0] = "modified";

113

3.
return x === arguments[0];
}
function nonstrict(x) {
arguments[0] = "modified";
return x === arguments[0];
}
strict("unmodified");

// false

nonstrict("unmodified"); // true

, arguments.
,
. :
var args = [].slice.call(arguments);

slice
,
Array. -
Array,
.
callMethod,
,
obj method, slice
, 2:
function callMethod(obj, method) {
var args = [].slice.call(arguments, 2);
return obj[method].apply(obj, args);
}

callMethod , :
var obj = {
add: function(x, y) { return x + y; }
};

114

callMethod(obj, "add", 17, 25); // 42

24. arguments

arguments.
arguments
, [].slice.call(arguments).

24



arguments

, . API next,
. ,
,
,
:
var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);
it.next(); // 1
it.next(); // 4
it.next(); // 1

values , , arguments:
function values() {
var i = 0, n = arguments.length;
return {
hasNext: function() {
return i < n;
},
next: function() {

115

3.
if (i >= n) {
throw new Error(" ");
}
return arguments[i++]; //
//
}
};
}

,
-:
var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);
it.next(); // (undefined)
it.next(); // (undefined)
it.next(); // (undefined)

, arguments .
arguments
values, next
arguments.
arguments[i++], it.next,
arguments, .
:
arguments
,
:
function values() {
var i = 0, n = arguments.length, a = arguments;
return {
hasNext: function() {
return i < n;
},
next: function() {
if (i >= n) {
throw new Error(" ");

116

25. bind
return a[i++];
}
};
}
var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);
it.next(); // 1
it.next(); // 4
it.next(); // 1

arguments .
arguments ,
arguments,
.

25

bind

,
,

. ,
,
.
, ,
:
var buffer = {
entries: [],

117

3.
add: function(s) {
this.entries.push(s);
},
concat: function() {
return this.entries.join("");
}
};

add
ES5 forEach:
var source = ["867", "-", "5309"];
source.forEach(buffer.add); // :
// (undefined)

buffer.add .
, ,
.
forEach, - . , forEach
.
entries,
. ,
forEach
, ,
:
var source = ["867", "-", "5309"];
source.forEach(buffer.add, buffer);
buffer.join(); // "867-5309"

118

,
. forEach ,
?
,
buffer.add:

25. bind
var source = ["867", "-", "5309"];
source.forEach(function(s) {
buffer.add(s);
});
buffer.join(); // "867-5309"

-,
add . , -
this. -
, -
call,
.
, ,
, ES5
.
bind, -
-,
. bind,
:
var source = ["867", "-", "5309"];
source.forEach(buffer.add.bind(buffer));
buffer.join(); // "867-5309"

, buffer.add.bind(buffer)
buffer.add ,
. , ,
,
. ,
:
buffer.add === buffer.add.bind(buffer); // false

, ,
, bind
, .
, --

119

3.

: -
.
(
4.)

,
.


.
, , bind.

26

bind

bind
.
URL-
:
function simpleURL(protocol, domain, path) {
return protocol + "://" + domain + "/" + path;
}


URL- .
ES5- map :
var urls = paths.map(function(path) {
return simpleURL("http", siteDomain, path);

120

});

26. bind

,

map ;
simpleURL ,
. simpleURL
bind:
var urls = paths.map(simpleURL.bind(null, "http",
siteDomain));

simpleURL.bind , simpleURL. ,
bind . ( simpleURL this,
,
null undefined.) , simpleURL,

simpleURL.bind , . , simpleURL.bind
path, simpleURL("http",
siteDomain, path).
(currying)
(Haskell
Curry), .

-.

, ,
,
bind.
, ,
null undefined.

3.

27


, .
, map forEach,
JavaScript - (.7).
, eval.
, ,
?
, .
:
.
:
function repeat(n, action) {
for (var i = 0; i < n; i++) {
eval(action);
}
}


,
, , eval
. , ,
,
start end:
var start = [], end = [], timings = [];
repeat(1000,
"start.push(Date.now()); f();

122

end.push(Date.now())");

27. ,
for (var i = 0, n = start.length; i < n; i++) {
timings[i] = end[i] - start[i];
}

. , start end
:
function benchmark() {
var start = [], end = [], timings = [];
repeat(1000,
"start.push(Date.now()); f();
end.push(Date.now())");
for (var i = 0, n = start.length; i < n; i++) {
timings[i] = end[i] - start[i];
}
return timings;
}

repeat
start end.
,
benchmark ReferenceError. ,
, push - ,
start end,
.
API-
:
function repeat(n, action) {
for (var i = 0; i < n; i++) {
action();
}
}

, benchmark
,

:

123

3.
function benchmark() {
var start = [], end = [], timings = [];
repeat(1000, function() {
start.push(Date.now());
f();
end.push(Date.now());
});
for (var i = 0, n = start.length; i < n; i++) {
timings[i] = end[i] - start[i];
}
return timings;
}

, eval, , , ,
,
, .
,
,
,
.

, API,
eval.
API-,
, , eval.

28

124


toString

JavaScript
:

28. toString
(function(x) {
return x + 1;
}).toString(); // "function (x)
// {\n

return x + 1;\n}"

-
,
.
toString .
, ECMAScript
, toString.
, JavaScript- , ,
.
, JavaScript-
, JavaScript.

, :
(function(x) {
return x + 1;
}).bind(16).toString(); // "function (x)
// {\n

[native code]\n}"

bind ( C++),
, JavaScript, .
toString,
, JavaScript-,
.
JavaScript (, ) ,

.

125

3.

, , toString, , , . :
(function(x) {
return function(y) {
return x + y;
}
})(42).toString(); // "function (y)
// {\n

return x + y;\n}"

, -
x, , x 42.

,
. JavaScript-
. , JavaScript ,
.

toString JavaScript-
.
- , toString
.
toString , .
, toString .

126

29.

29

JavaScript-
: (
. 64).
arguments
: arguments.callee
, arguments, arguments.caller ,
. -
, ,

:
var factorial = (function(n) {
return (n <= 1) ? 1 : (n * arguments.callee(n - 1));
});

,
:
function factorial(n) {
return (n <= 1) ? 1 : (n * factorial(n - 1));
}

arguments.caller : , arguments.
,
. JavaScript
,
caller ,
:
function revealCaller() {
return revealCaller.caller;
}

127

3.
function start() {
return revealCaller();
}
start() === start; // true

,

.
:
function getCallStack() {
var stack = [];
for (var f = getCallStack.caller; f; f = f.caller)
{
stack.push(f);
}
return stack;
}

getCallStack :
function f1() {
return getCallStack();
}
function f2() {
return f1();
}
var trace = f2();
trace; // [f1, f2]

getCallStack :
,
!
function f(n) {
return n === 0 ? getCallStack() : f(n - 1);
}
var trace = f(1); //

128

29.

? f
, caller
, f.
getCallStack , f.
,
, f
,
.


. ,

ES5;
caller callee arguments :
function f() {
"use strict";
return f.caller;
}
f(); // : caller
//


. , .

arguments.caller arguments.callee, .
caller , .

129

4.

JavaScript . . ,
.
- ,
JavaScript :
.
,
JavaScript ,
. JavaScript
- ,
.

130

,
, .
JavaScript .
.
- ,
. ,
-
.

30.

30



prototype, getPrototypeOf
__proto__

,
,
prototype. .
.
yy C.prototype ,
new C().
yy Object.getPrototypeOf(obj)
( ES5)
obj.
yy obj.__proto__
obj.
, JavaScript.
User , new ,
:
function User(name, passwordHash) {
this.name = name;
this.passwordHash = passwordHash;
}
User.prototype.toString = function() {
return "[User " + this.name + "]";
};
User.prototype.checkPassword = function(password) {
return hash(password) === this.passwordHash;
};
var u = new User("sfalken",
"0ef33ae791068ec64b502d6cb0191387");

131

4.

User
prototype, , - .
User.prototype :
toString checkPassword.
User new, u , User.prototype,
-.
.4.1.

132

. 4.1. User

30.

, u - User.prototype.
.

, u.name u.passwordHash,
u. ,
u,
u. , u.checkPassword
, User.prototype.
.
prototype -

, ES5
Object.getPrototypeOf() .
, , u

:
Object.getPrototypeOf(u) === User.prototype; // true


__proto__.
,
ES5- Object.getPrototypeOf.
:
u.__proto__ === User.prototype // true

, : JavaScript User ,
. JavaScript - (User)
-, (User.prototype).
. 4.2
User. User
, User.prototype
,

133

4.

. User u
- .

. 4.2. User

C.prototype new C().


Object.getPrototypeOf(obj) , ES5 .
obj.__proto__ .
, - .

31. Object.getPrototypeOf

31


Object.
getPrototypeOf,
__proto__

API- - ES5 Object.


getPrototypeOf, ,
JavaScript- __proto__.
JavaScript-,
, ,
. , ,
null.
__proto__ Object.prototype, , null
__proto__:
var empty = Object.create(null); // ,

"__proto__" in empty;

// false (
)

__proto__
:
var empty = Object.create(null); // ,

"__proto__" in empty;

// true (
)

Object.getPrototypeOf,

.
, __proto__
- ,
(.45). , JavaScript,
, __proto__.

135

4.

Object.getPrototypeOf,
,
__proto__ .
JavaScript-, API, ES5,

__proto__:
if (typeof Object.getPrototypeOf === "undefined") {
Object.getPrototypeOf = function(obj) {
var t = typeof obj;
if (!obj || (t !== "object" && t !== "function"))
{
throw new TypeError(" ");
}
return obj.__proto__;
};
}


, ES5,
, Object.getPrototypeOf
.

Object.
getPrototypeOf, __proto__.
Object.getPrototypeOf ,
__proto__ ES5.

32

136


__proto__

__proto__ ,

32. __proto__
Object.getPrototypeOf, -

-.
( ,
, ?),
.
:

, ,
__proto__.
, __proto__, .
JavaScript-
,
, JavaScript-.
, .
, ,
, ,
. __proto__
, , ,
,
,
.
, __proto__, .
,
.
.
- ,
, ,
.

137

4.



ES5 Object.create. ,
ES5,
Object.create,
__proto__ (.33).

__proto__ .

Object.create.

33


,

new

, User
(.30), ,
new.
, , :
function User(name, passwordHash) {
this.name = name;
this.passwordHash = passwordHash;
}


new,
:
var u = User("baravelli",

138

"d8b74df393528d51cd19980ae0aa028e");

33. , new
u;
this.name;
this.passwordHash;

// undefined
// "baravelli"
//

"d8b74df393528d51cd19980ae0aa028e"


undefined,
( , )
name passwordHash.
User ES5,
undefined:
function User(name, passwordHash) {
"use strict";
this.name = name;
this.passwordHash = passwordHash;
}
var u = User("baravelli",
"d8b74df393528d51cd19980ae0aa028e");
// :

: User this.name,

TypeError. ,
,
.
User
. new,
,
.
,
.
,
User:
function User(name, passwordHash) {
if (!(this instanceof User)) {

139

4.
return new User(name, passwordHash);
}
this.name = name;
this.passwordHash = passwordHash;
}

User ,
User.prototype
, :
-:
var x = User("baravelli",
"d8b74df393528d51cd19980ae0aa028e");
var y = new User("baravelli",
"d8b74df393528d51cd19980ae0aa028e");
x instanceof User; // true
y instanceof User; // true


, .
(.21 22)
- apply,

.

ES5 Object.create:
function User(name, passwordHash) {
var self = this instanceof User
? this
: Object.create(User.prototype);
self.name = name;
self.passwordHash = passwordHash;
return self;
}

140

Object.create - , .
, User
, , User.prototype
name passwordHash.

33. , new

Object.create , ES5,

new:
if (typeof Object.create === "undefined") {
Object.create = function(prototype) {
function C() { }
C.prototype = prototype;
return new C();
};
}

( , Object.
create, .
,
.)
, -
User new?
,
. ,
JavaScript new , -
return. User self, new self,
, this.
,
,
. ,
. , , -
new ,

.

141

4.

, ;
new
Object.create.
new,
.

34

JavaScript .
User 30 ,
:
function User(name, passwordHash) {
this.name = name;
this.passwordHash = passwordHash;
this.toString = function() {
return "[User " + this.name + "]";
};
this.checkPassword = function(password) {
return hash(password) === this.passwordHash;
};
}

, .
User,
:
var u1 = new User(/* ... */);
var u2 = new User(/* ... */);
var u3 = new User(/* ... */);

142

.4.3 ,
-. -

34.

toString checkPassword ,
,
.

. 4.3. -

.4.4 ,
- . toString checkPassword

.
,

. ,
,
,
u3.toString(), toString ?
JavaScript-
, -

143

4.

. , .

. 4.4. -

-
, -.
, .

35

144

JavaScript -
,

35.

.
, ,
. ,
for...in ES5
Object.keys() Object.getOwnPropertyNames(),
.
JavaScript-
, -
. , ,
(_).
, ,
,
,
.

. ,
-

,
. ,
, ,
.
JavaScript
.
.
, .

. ,
:

145

4.

, .
.
,
,
.
User 30:
function User(name, passwordHash) {
this.toString = function() {
return "[User " + name + "]";
};
this.checkPassword = function(password) {
return hash(password) === passwordHash;
};
}

, ,
toString checkPassword name passwordHash ,
this. User
, ,

User.
,
, ,
-. 34 ,
.
,
, .

.
.

36. -

36


, -
.
,
.
, ,
,
.
:
function Tree(x) {
this.value = x;
}
Tree.prototype = {
children: [], //
// !
addChild: function(x) {
this.children.push(x);
}
};

, ,

:
var left = new Tree(2);
left.addChild(1);
left.addChild(3);
var right = new Tree(6);
right.addChild(5);
right.addChild(7);
var top = new Tree(4);
top.addChild(left);

147

4.
top.addChild(right);
top.children; // [1, 3, 5, 7, left, right]

addChild
Tree.prototype.children,
(!) addChild. Tree, .4.5.

. 4.5. -

Tree children
:
function Tree(x) {
this.value = x;
this.children = []; //
}
Tree.prototype = {
addChild: function(x) {
this.children.push(x);
}

148

};

36. -

,
, .4.6.

. 4.6. -

, ,
, .

, , ,
,

this. ( ,
this -
, ,
.)
, . ,
,
, .
, -, .
, ,
-.

149

4.

,
.
, , -.

37


this

CSV (Comma-Separated Values , )


:
Bsendorfer,1828,Vienna,Austria
Fazioli,1981,Sacile,Italy
Steinway,1853,New York,USA

CSV- . ( ,
,
, "hello, world".)
, CSV ,
.
-
,
:
function CSVReader(separators) {
this.separators = separators || [","];
this.regexp = new RegExp(this.separators.
map(function(sep) {
return "\\" + sep[0];
}).join("|"));

150

37. this

read
:
,
.
.
map:
CSVReader.prototype.read = function(str) {
var lines = str.trim().split(/\n/);
return lines.map(function(line) {
return line.split(this.regexp); //
// !
});
};
var reader = new CSVReader();
reader.read("a,b,c\nd,e,f\n"); // [["a,b,c"],
// ["d,e,f"]]

, , , : ,
, lines.map this,
regexp CSVReader. map
lines, . this.
regexp undefined, line.split
.
,
this , . 18 25,
this, .
,
,
: , var . , this .
, this CSVReader.prototype.read
this ,
lines.map.

151

4.

, forEach, 25, , map, ,


,
this
. ,

this
map:
CSVReader.prototype.read = function(str) {
var lines = str.trim().split(/\n/);
return lines.map(function(line) {
return line.split(this.regexp);
}, this); // this
//
};
var reader = new CSVReader();
reader.read("a,b,c\nd,e,f\n");
// [["a","b","c"], ["d","e","f"]]


API-,
. , map
? this
, this.
: this

:
CSVReader.prototype.read = function(str) {
var lines = str.trim().split(/\n/);
var self = this; //
// this
return lines.map(function(line) {
return line.split(self.regexp);

152

// this

37. this
});
};
var reader = new CSVReader();
reader.read("a,b,c\nd,e,f\n");
// [["a","b","c"], ["d","e","f"]]


self, ,
this . (

me that.)
,

.
ES5
bind,
, 25:
CSVReader.prototype.read = function(str) {
var lines = str.trim().split(/\n/);
return lines.map(function(line) {
return line.split(this.regexp);
}.bind(this)); // this
};
var reader = new CSVReader();
reader.read("a,b,c\nd,e,f\n");
// [["a","b","c"], ["d","e","f"]]

this
.
this , , self, me
that.

4.

38

(scene graph) ,
,
. ,
(actors), ,
, (context):
function Scene(context, width, height, images) {
this.context = context;
this.width = width;
this.height = height;
this.images = images;
this.actors = [];
}
Scene.prototype.register = function(actor) {
this.actors.push(actor);
};
Scene.prototype.unregister = function(actor) {
var i = this.actors.indexOf(actor);
if (i >= 0) {
this.actors.splice(i, 1);
}
};
Scene.prototype.draw = function() {
this.context.clearRect(0, 0, this.width,
this.height);
for (var a = this.actors, i = 0, n = a.length;
i < n;
i++) {
a[i].draw();
}

154

};

38.

Actor,
.
, , :
function Actor(scene, x, y) {
this.scene = scene;
this.x = x;
this.y = y;
scene.register(this);
}


, moveTo,
, :
Actor.prototype.moveTo = function(x, y) {
this.x = x;
this.y = y;
this.scene.draw();
};

,
:
Actor.prototype.exit = function() {
this.scene.unregister(this);
this.scene.draw();
};

,
. ,
type,
. , ,
(
HTML- Canvas API, Image <canvas> -
drawImage):
Actor.prototype.draw = function() {
var image = this.scene.images[this.type];

155

4.
this.scene.context.drawImage(image, this.x, this.y);
};


:
Actor.prototype.width = function() {
return this.scene.images[this.type].width;
};
Actor.prototype.height = function() {
return this.scene.images[this.type].height;
};


Actor. ,
(spaceship) SpaceShip,
Actor. , SpaceShip
-.
SpaceShip ,
Actor.
Actor , :
function SpaceShip(scene, x, y) {
Actor.call(this, scene, x, y);
this.points = 0;
}

Actor
,
Actor.
SpaceShip , .
SpaceShip
Actor, Actor.
prototype.
ES5 Object.create:
SpaceShip.prototype = Object.create(Actor.prototype);

156

( 33 Object.create
, ES5.)

38.

- Space
Ship Actor ,
. ,
Actor
:
SpaceShip.prototype = new Actor();

SpaceShip,
. , SpaceShip
x y.
SpaceShip, SpaceShip.prototype. ,
Actor ,

SpaceShip.
:
, .
- SpaceShip
, , type ,
, :
SpaceShip.prototype.type = "spaceShip";
SpaceShip.prototype.scorePoint = function() {
this.points++;
};
SpaceShip.prototype.left = function() {
this.moveTo(Math.max(this.x - 10, 0), this.y);
};
SpaceShip.prototype.right = function() {
var maxWidth = this.scene.width - this.width();
this.moveTo(Math.min(this.x + 10, maxWidth),
this.y);
};

157

4.

.4.7
SpaceShip. , scene,
x y -,
-, Actor.

. 4.7.

158

39.

, this.
, Object.create.

39

,
38
,
.
Actor :
function Actor(scene, x, y) {
this.scene = scene;
this.x = x;
this.y = y;
this.id = ++Actor.nextID;
scene.register(this);
}
Actor.nextID = 0;

Actor , , Alien
(),
.
,
:
function Alien(scene, x, y, direction, speed,
strength) {
Actor.call(this, scene, x, y);

159

4.
this.direction = direction;
this.speed = speed;
this.strength = strength;
this.damage = 0;
this.id = ++Alien.nextID; //
// !
}
Alien.nextID = 0;


Alien Actor: id.
(
, , ),
, , .

, , .
,
, ,
.

Actor Alien :
function Actor(scene, x, y) {
this.scene = scene;
this.x = x;
this.y = y;
this.actorID = ++Actor.nextID; //
// alienID
scene.register(this);
}
Actor.nextID = 0;
function Alien(scene, x, y, direction, speed,

160

strength) {

40.
Actor.call(this, scene, x, y);
this.direction = direction;
this.speed = speed;
this.strength = strength;
this.damage = 0;
this.alienID = ++Alien.nextID; //
// actorID
}
Alien.nextID = 0;

,
.
.

40

ECMAScript , ,
Array, Function Date. , , ,
,

.
Array .

,
:
function Dir(path, entries) {
this.path = path;

161

4.
for (var i = 0, n = entries.length; i < n; i++) {
this[i] = entries[i];
}
}
Dir.prototype = Object.create(Array.prototype);
// Array

,
length :
var dir = new Dir("/tmp/mysite", ["index.html",
"script.js", "style.css"]);
dir.length; // 0

, length ,
. ECMAScript
[[Class]]. , JavaScript
. [[Class]]
: (
Array []) "Array" [[Class]],
"Function" [[Class]] ..
[[Class]], ECMAScript, .4.1.

162

,
[[Class]] length ? ,
length
, [[Class]]
Array. length

.
, length ,
length, ,
, .

40.
4.1. [[Class]], ECMAScript
[[Class]]

"Array"

new Array(...), [...]

"Boolean"

new Boolean(...)

"Date"

new Date(...)

"Error"

new Error(...), new EvalError(...),


new RangeError(...), new ReferenceError(...),
new SyntaxError(...), new TypeError(...),
new URIError(...)

"Function"

new Function(...), function(...) {...}

"JSON"

JSON

"Math"

Math

"Number"

new Number(...)

"Object"

new Object(...), {...}, new MyClass(...)

"RegExp"

new RegExp (...), /.../

"String"

new String (...)

Array, new Array()


[] .
Dir [[Class]]
"Object". : Object.
prototype.toString
[[Class]]
,
:
var dir = new Dir("/", []);
Object.prototype.toString.call(dir); // "[object Object]"
Object.prototype.toString.call([]);

// "[objectArray]"

Dir length,
.
:

163

4.
function Dir(path, entries) {
this.path = path;
this.entries = entries; //
}

Array
entries:
Dir.prototype.forEach = function(f, thisArg) {
if (typeof thisArg === "undefined") {
thisArg = this;
}
this.entries.forEach(f, thisArg);
};


ECMAScript ,

[[Class]]
, .
: Array, Boolean, Date,
Function, Number, RegExp String.

-
, [[Class]].
,
.

41

,
.

41.


.
,
.
,
,
, .
:
.
JavaScript (introspection)
. Object.prototype.hasOwnProperty ,
(
), . Object.getPrototypeOf __proto__
(.30)
. .
,
. ,
,
.
, , , .
,
: , (
)
.
, JavaScript
(.35).

. ,
,
.

165

4.

, .
,
.
,
, .

42


41
. , ,
, .

(monkey-patching).

. ?
:
Array.prototype.split = function(i) { // 1
return [this.slice(0, i), this.slice(i)];
};

:
split.

166

,
. ,
Array.prototype,
:

42.
Array.prototype.split = function() { // 2
var i = Math.floor(this.length / 2);
return [this.slice(0, i), this.slice(i)];
};

split
50% ,
, ,
.
, ,
, Array.prototype,
, . ,
,
. , ,
,
.
,

, ,
:
function addArrayMethods() {
Array.prototype.split = function(i) {
return [this.slice(0, i), this.slice(i)];
};
};

,
, ,
addArrayMethods , Array.
prototype.split. , (polyfill). JavaScript-
JavaScript- ,
- .
API. , ES5
, forEach, map filter, -

167

4.

.

,
.
,
. ,

( ,
),
API-.

, :
if (typeof Array.prototype.map !== "function") {
Array.prototype.map = function(f, thisArg) {
var result = [];
for (var i = 0, n = this.length; i < n; i++) {
result[i] = f.call(thisArg, this[i], i);
}
return result;
};
}

Array.prototype.map , , , ,
, .

.
, .
.
,
API-.

5.

JavaScript
.

-, -
, -. ,

. .
:
.

43

JavaScript- , .
:
.
JavaScript
for...in:

169

5.
var dict = { alice: 34, bob: 24, chris: 62 };
var people = [];
for (var name in dict) {
people.push(name + ": " + dict[name]);
}
people; // ["alice: 34", "bob: 24", "chris: 62"]

- (.4), for...in
, . , , ,
,
-?
function NaiveDict() { }
NaiveDict.prototype.count = function() {
var i = 0;
for (var name in this) { //
//
i++;
}
return i;
};
NaiveDict.prototype.toString = function() {
return "[object NaiveDict]";
};
var dict = new NaiveDict();
dict.alice = 34;
dict.bob = 24;
dict.chris = 62;
dict.count(); // 5

170

,

NaiveDict (count, toString),
(alice, bob, chris).

43.

count ,
(count, toString, alice, bob, chris),
,
. Dict,
,
dict.get(key) dict.
set(key, value), 45.
.

Array.
, , Perl PHP,
.
JavaScript-
, , ,
:
var dict = new Array();
dict.alice = 34;
dict.bob = 24;
dict.chris = 62;
dict.bob; // 24

, , -
. , - , ,

Array.prototype:
Array.prototype.first = function() {
return this[0];
};
Array.prototype.last = function() {
return this[this.length 1];
};

171

5.

, ,
:
var names = [];
for (var name in dict) {
names.push(name);
}
names; // ["alice", "bob", "chris", "first", "last"]

:
Object, , NaiveDict,
, , . ,
new Array() new Object() .
:
var dict = {};
dict.alice = 34;
dict.bob = 24;
dict.chris = 62;
var names = [];
for (var name in dict) {
names.push(name);
}
names; // ["alice", "bob", "chris"]

. Object.prototype,
.
Object, ,
Object.prototype.

172

- ? ,
47 , -

44. null

Object.prototype ,
for...in.
Array.prototype
. , 42 ,
Array.prototype
, . ,
for...in.
, , , , , .
Object ( , 47),
for...in .
! 44 45,
, .
.
, , ,
45 Dict.

.
for...in ,
Object.prototype.

44


null

.
ES5
.

173

5.

prototype null undefined:


function C() { }
C.prototype = null;


Object:
var o = new C();
Object.getPrototypeOf(o) === null;
// false
Object.getPrototypeOf(o) === Object.prototype;
// true

ES5
. Object.create
,
,
(property descriptor map),
.
null , - :
var x = Object.create(null);
Object.getPrototypeOf(o) === null;

// true


.
JavaScript-, Object.create , ,
.

__proto__ (. 31 32).

null :
var x = { __proto__: null };
x instanceof Object;

174

// false ( )

44. null

, , Object.create,
. __proto__

. JavaScript-
,

Object.create.
, __proto__ ,
,
. 45 ,
JavaScript- "__proto__"
, .
, "__proto__"

,
Dict,
45.

, , , ES5,
Object.create(null).

{__proto__: null}.
__proto__ ,
,
JavaScript-.
__proto__ ,

.

175

5.

45


hasOwnProperty

43 44 ,
.

JavaScript-:
"alice" in dict;

//

dict.alice;

//

dict.alice = 24;

//

, JavaScript
. Object.prototype :
var dict = {};
"alice" in dict;

// false

"bob" in dict;

// false

"chris" in dict;

// false

"toString" in dict;

// true

"valueOf" in dict;

// true

, Object.prototype hasOwnProperty, ,

:
dict.hasOwnProperty("alice");

// false

dict.hasOwnProperty("toString"); // false
dict.hasOwnProperty("valueOf");

// false

, :
dict.hasOwnProperty("alice") ? dict.alice : undefined;
dict.hasOwnProperty(x) ? dict[x] : undefined;

176

, . dict.hasOwnProperty hasOwnProperty

45. hasOwnProperty

dict. Object.
prototype.
"hasOwnProperty",
:
dict.hasOwnProperty = 10;
dict.hasOwnProperty("alice");
// : dict.hasOwnProperty

, ,
,
"hasOwnProperty". , ,
.
,
, , ,
, .
.
hasOwnProperty
call,
20. hasOwnProperty :
var hasOwn = Object.prototype.hasOwnProperty;

:
var hasOwn = {}.hasOwnProperty;

, ,
, , call:
hasOwn.call(dict, "alice");

, hasOwnProperty :
var dict = {};
dict.alice = 24;
hasOwn.call(dict, "hasOwnProperty"); // false

177

5.
hasOwn.call(dict, "alice");

// true

dict.hasOwnProperty = 10;
hasOwn.call(dict, "hasOwnProperty"); // true
hasOwn.call(dict, "alice");

// true

, ,
Dict,
:
function Dict(elements) {
//

this.elements = elements || {};


// Object
}
Dict.prototype.has = function(key) {
//
return {}.hasOwnProperty.call(this.elements, key);
};
Dict.prototype.get = function(key) {
//
return this.has(key)
? this.elements[key]
: undefined;
};
Dict.prototype.set = function(key, val) {
this.elements[key] = val;
};
Dict.prototype.remove = function(key) {
delete this.elements[key];
};

178

,
Dict.prototype.set, -

45. hasOwnProperty


elements, Object.prototype
.

, JavaScript-:
var dict = new Dict({
alice: 34,
bob: 24,
chris: 62
});
dict.has("alice");

// true

dict.get("bob");

// 24

dict.has("valueOf"); // false

, 44 , __proto__
.
__proto__ Object.prototype,
( )
:
var empty = Object.create(null);
"__proto__" in empty;
// false ( )
var hasOwn = {}.hasOwnProperty;
hasOwn.call(empty, "__proto__");
// false ( )

true in:
var empty = Object.create(null);
"__proto__" in empty;
// true ( )
var hasOwn = {}.hasOwnProperty;
hasOwn.call(empty, "__proto__");
// false ( )

179

5.

, , -
__proto__:
var empty = Object.create(null);
"__proto__" in empty;

// true (
// )

var hasOwn = {}.hasOwnProperty;


hasOwn.call(empty, "__proto__"); // true (
// )

, ,
,
:
var dict = new Dict();
dict.has("__proto__"); // ?

,
Dict
"__proto__", ,
:
function Dict(elements) {
//
//
this.elements = elements || {};
// Object
this.hasSpecialProto = false;
// "__proto__"?
this.specialProto = undefined;
// "__proto__"
}
Dict.prototype.has = function(key) {
if (key === "__proto__") {
return this.hasSpecialProto;
}

180

45. hasOwnProperty
//
return {}.hasOwnProperty.call(this.elements, key);
};
Dict.prototype.get = function(key) {
if (key === "__proto__") {
return this.specialProto;
}
//
return this.has(key)
? this.elements[key]
: undefined;
};
Dict.prototype.set = function(key, val) {
if (key === "__proto__") {
this.hasSpecialProto = true;
this.specialProto = val;
} else {
this.elements[key] = val;
}
};
Dict.prototype.remove = function(key) {
if (key === "__proto__") {
this.hasSpecialProto = false;
this.specialProto = undefined;
} else {
delete this.elements[key];
}
};

, __proto__,
-
:
var dict = new Dict();
dict.has("__proto__"); // false

181

5.

, has
OwnProperty.
hasOwnProperty ,
call.
, hasOwnProperty.
__proto__ .

46

JavaScript-
.
, .
ECMAScript -

.

182

: for...in
- . JavaScript-
,
. API-, ,
, , :

46. ,
function report(highScores) {
var result = "";
var i = 1;
for (var name in highScores) { //
//
result += i + ". " + name + ": " +
highScores[name] + "\n";
i++;
}
return result;
}
report([{ name: "Hank", points: 1110100 },
{ name: "Steve", points: 1064500 },
{ name: "Billy", points: 1050200 }]);
// ?

,
,
.
, .
JavaScript-, ,
- for...in.

, ,
.
report
JavaScript-, API-
, :
function report(highScores) {
var result = "";
for (var i = 0, n = highScores.length; i < n; i++)
{
var score = highScores[i];

183

5.
result += (i + 1) + ". " +
score.name + ": " +
score.points + "\n";
}
return result;
}
report([{ name: "Hank", points: 1110100 },
{ name: "Steve", points: 1064500 },
{ name: "Billy", points: 1050200 }]);
// "1. Hank: 1110100\n2. Steve: 1064500\n3.
// Billy: 1050200\n"

,
name points,
: 0 highScores.length 1.
.
, :
var ratings = {
"Good Will Hunting": 0.8,
"Mystic River": 0.7,
"21": 0.6,
"Doubt": 0.9
};

2,
.
:
var total = 0, count = 0;
for (var key in ratings) { //
total += ratings[key];
count++;

184

46. ,
total /= count;
total; // ?

, JavaScript-
. ,
,
,
:
(0.8 + 0.7 + 0.6 + 0.9) / 4

// 0.75

, .
21
, ,
:
(0.6 + 0.8 + 0.7 + 0.9) / 4

// 0.7499999999999999

,
.

:
(8 + 7 + 6 + 9) / 4 / 10

// 0.75

(6 + 8 + 7 + 9) / 4 / 10

// 0.75

, for...in
,
.

for...
in.

.
.

5.

47


Object.prototype

for...in , ,
43, .
for...in . : for...in
,
Object.prototype .
: , Object.prototype ,
?
, , allKeys,
?
Object.prototype.allKeys = function() {
var result = [];
for (var key in this) {
result.push(key);
}
return result;
};

,
:
({ a: 1, b: 2, c: 3 }).allKeys(); // ["allKeys", "a",
//

186

"b", "c"]

,
allKeys, Object.prototype. ,
,
.
Object.prototype
for...in.

47. Object.prototype

,

allKeys , :
function allKeys(obj) {
var result = [];
for (var key in obj) {
result.push(key);
}
return result;
}

Object.prototype
, ES5 , . Object.
defineProperty
,
. ,
, ,
for...in,
enumerable false:
Object.defineProperty(Object.prototype, "allKeys", {
value: function() {
var result = [];
for (var key in this) {
result.push(key);
}
return result;
},
writable: true,
enumerable: false,
configurable: true
});

, ,
, ,
for...in Object.
,
. ,

187

5.

for...in, Object.
defineProperty .

Object.prototype.
Object.prototype
.
Object.prototype,

ES5 Object.defineProperty.

48

,
:
function Member(name) {
this.name = name;
this.friends = [];
}
var a
b
c
d
e
f

=
=
=
=
=
=

new
new
new
new
new
new

Member("Alice"),
Member("Bob"),
Member("Carol"),
Member("Dieter"),
Member("Eli"),
Member("Fatima");

a.friends.push(b);
b.friends.push(c);
c.friends.push(e);
d.friends.push(b);
e.friends.push(d, f);

188


(.5.1).

48.

, ,

. for...in:
Member.prototype.inNetwork = function(other) {
var visited = {};
var workset = {};
workset[this.name] = this;
for (var name in workset) {
var member = workset[name];
delete workset[name];
//
//
if (name in visited) { //
//
//
continue;
}
visited[name] = member;
if (member === other) { // ?
return true;
}
member.friends.forEach(function(friend) {
workset[friend.name] = friend;
});
}
return false;
};

Carol

Alice

Bob

Eli

Fatima

Dieter

. 5.1.

189

5.

, JavaScript-
:
a.inNetwork(f); // false

? , for...in , ,
. , ECMAScript JavaScript-
, - . ,
.

,
.

:
, for...in
.
,
.
,
. WorkSet,
:
function WorkSet() {
this.entries = new Dict();
this.count = 0;
}

190

WorkSet.prototype.isEmpty = function() {
return this.count === 0;
};
WorkSet.prototype.add = function(key, val) {
if (this.entries.has(key)) {
return;
}

48.
this.entries.set(key, val);
this.count++;
};
WorkSet.prototype.get = function(key) {
return this.entries.get(key);
};
WorkSet.prototype.remove = function(key) {
if (!this.entries.has(key)) {
return;
}
this.entries.remove(key);
this.count--;
};

,
Dict:
Dict.prototype.pick = function() {
for (var key in this.elements) {
if (this.has(key)) {
return key;
}
}
throw new Error(" ");
};
WorkSet.prototype.pick = function() {
return this.entries.pick();
};

inNetwork
while,
:
Member.prototype.inNetwork = function(other) {
var visited = {};
var workset = new WorkSet();
workset.add(this.name, this);
while (!workset.isEmpty()) {
var name = workset.pick();
var member = workset.get(name);
workset.remove(name);

191

5.
if (name in visited) {
//
continue;
}
visited[name] = member;
if (member === other) { // ?
return true;
}
member.friends.forEach(function(friend) {
workset.add(friend.name, friend);
});
}
return false;
};

pick ,
, .
, for...in JavaScript- (
)
.
, . , ,
.
. ,
;

; ,
, ,
.
,
,
.

192


.
, inNetwork
:

48.
Member.prototype.inNetwork = function(other) {
var visited = {};
var worklist = [this];
while (worklist.length > 0) {
var member = worklist.pop();
if (member.name in visited) {
//
continue;
}
visited[member.name] = member;
if (member === other) {
// ?
return true;
}
member.friends.forEach(function(friend) {
worklist.push(friend);
//
});
}
return false;
};

inNetwork
. ,
, true,
. ,
, inNetwork,
.


for...in.
,
, for...in while
for.

, - , , , .

5.

49




for, for...in

(mean) :
var scores = [98, 74, 85, 77, 93, 100, 89];
var total = 0;
for (var score in scores) {
total += score;
}
var mean = total / scores.length;
mean; // ?

? , 88, ,
, .
:
.
for...in .
,
:
(0+1++6)/7=21
. ,
,
. += ,

total, "00123456". ? mean
17636.571428571428.

for:
var scores = [98, 74, 85, 77, 93, 100, 89];
var total = 0;

194

for (var i = 0, n = scores.length; i < n; i++) {

49. for
total += scores[i];
}
var mean = total / scores.length;
mean; // 88

, , ,
,
. ,

, -
.
n for.
, :
for (var i = 0; i < scores.length; i++) { ... }

,
.
, JavaScript , scores.length.
, ,
.


for, for...in.

,
.

195

5.

50


.
, ,
, .
, ,

.
JavaScript for , ,
, C, Java C#,

-.

:
for (var i = 0; i <= n; i++) { ... }
//
for (var i = 1; i < n; i++) { ... }
//
for (var i = n; i >= 0; i--) { ... }
//
for (var i = n - 1; i > 0; i--) { ... }
//

:
.
,
.
, JavaScript , , (.11).

196

50.

ES5 .
Array.prototype.forEach.
:
for (var i = 0, n = players.length; i < n; i++) {
players[i].score++;
}

:
players.forEach(function(p) {
p.score++;
});

,
.
.
:
var trimmed = [];
for (var i = 0, n = input.length; i < n; i++) {
trimmed.push(input[i].trim());
}

,
forEach:
var trimmed = [];
input.forEach(function(s) {
trimmed.push(s.trim());
});

, ES5
Array.prototype.map,
:

197

5.
var trimmed = input.map(function(s) {
return s.trim();
});

,
.
Array.prototype.filter
: ,
,
, ,
. ,
- ,
:
listings.filter(function(listing) {
return listing.price >= min && listing.price <= max;
});

, , ES5. . , ,
,
,
:
function takeWhile(a, pred) {
var result = [];
for (var i = 0, n = a.length; i < n; i++) {
if (!pred(a[i], i)) {
break;
}
result[i] = a[i];
}
return result;
}
var prefix = takeWhile([1, 2, 4, 8, 16, 32],
function(n) {
return n < 10;

198

}); // [1, 2, 4, 8]

50.

, pred
i,
. ,
, forEach,
map filter,
.
takeWhile
, Array.prototype (
,
Array.prototype, 42):
Array.prototype.takeWhile = function(pred) {
var result = [];
for (var i = 0, n = this.length; i < n; i++) {
if (!pred(this[i], i)) {
break;
}
result[i] = this[i];
}
return result;
};
var prefix = [1, 2, 4, 8, 16, 32].
takeWhile(function(n) {
return n < 10;
}); // [1, 2, 4, 8]

,
,
, break
continue. , takeWhile, forEach:
function takeWhile(a, pred) {
var result = [];
a.forEach(function(x, i) {
if (!pred(x)) {
// ?
}
result[i] = x;

199

5.
});
return result;
}

,
,
, ,
:
function takeWhile(a, pred) {
var result = [];
var earlyExit = {}; //
//
try {
a.forEach(function(x, i) {
if (!pred(x)) {
throw earlyExit;
}
result[i] = x;
});
} catch (e) {
if (e !== earlyExit) { //
// earlyExit
throw e;
}
}
return result;
}

, ,
.

ES5 some every
. ,
, ,
. ,
some , ,

200

50.


:
[1, 10, 100].some(function(x) { return x > 5; });
// true
[1, 10, 100].some(function(x) { return x < 0; });
// false

, every , ,
:
[1, 2, 3, 4, 5].every(function(x) { return x > 0; });
// true
[1, 2, 3, 4, 5].every(function(x) { return x < 3; });
// false

:
some
, some ,
; ,
every ,
.

forEach,
. ,
takeWhile every:
function takeWhile(a, pred) {
var result = [];
a.every(function(x, i) {
if (!pred(x)) {
return false; //
}
result[i] = x;
return true;

//

});
return result;
}

201

5.


, for ,
Array.prototype.forEach Array.prototype.map.
, , .
, ,
some
every.

51



Array ,

Array.prototype
, ,
Array. , JavaScript ,
.

, 22. ,
Array.prototype,
arguments.forEach .
forEach
call (.20):
function highlight() {
[].forEach.call(arguments, function(widget) {
widget.setBackground("yellow");
});

202

51. Array

forEach Function, , Function.prototype call.


forEach
this ( arguments),
(
). ,
, .
,
-, DOM NodeList. ,
(document.getElementsByTagName),
-,
NodeLists. arguments, NodeList
, Array.prototype.
? -
:
yy length () 0...232 1.
yy length
. 0...232 2,
.
,

Array.prototype . ,
,
:
var arrayLike = { 0: "a", 1: "b", 2: "c", length: 3 };
var result = Array.prototype.map.call(arrayLike,
function(s) {
return s.toUpperCase();
}); // ["A", "B", "C"]

203

5.

length. ,
Array.prototype,
, :
var result = Array.prototype.map.call("abc",
function(s) {
return s.toUpperCase();
}); // ["A", "B", "C"]


JavaScript- - :
yy length n
,
n.
yy n,
length,
length n+ 1.
,
length. ,
,
Array.prototype,
length
.
Array,
, concat.
, ,
[[Class]] .
, ,
. , ,
arguments:
function namesColumn() {
return ["Names"].concat(arguments);

204

52. Array
namesColumn("Alice", "Bob", "Chris");
// ["Names", { 0: "Alice", 1: "Bob", 2: "Chris" }]

concat , , ,
.

slice , :
function namesColumn() {
return ["Names"].concat([].slice.call(arguments));
}
namesColumn("Alice", "Bob", "Chris");
// ["Names", "Alice", "Bob", "Chris"]

Array
, call.
Array
,
length.

52


,
Array

JavaScript
:
, .
:
var a = [1, 2, 3, 4, 5];

205

5.

Array:
var a = new Array(1, 2, 3, 4, 5);

, , Array
. ,
,
Array:
function f(Array) {
return new Array(1, 2, 3, 4, 5);
}
f(String); // new String(1)

,
Array:
Array = String;
new Array(1, 2, 3, 4, 5); // new String(1)

. Array ,
, :
, ,
length, .
, ["hello"] new Array("hello")
, [17] new Array(17)
! ,
,
,
.

Array ,
.
Array .

206

6.

API

-
API. ,
JavaScript-,

, -

. ,
.

, , . API .
API-
( , ,
!) ,
.

53

,
API , ,

207

6. API

. : ,
.
, ,
. ,
,

,
.
. , , , .

,
. ,
,
, :
var widget = new Widget(320, 240); // : 320,
// : 240

208

- ,
.
-, , -
( , HTML, CSS JavaScript).

, , ,
. ,
CSS- , ,
, (, ,
, ). API-
. .

53.

, !
,
.
API- (. 55),
. ,
-, . width height,
w h,
,
, .
, Widget , ,
.

setWidth, ,
width.

, -
.
,
,
.
,
,
,
.


.
, ,
, .

6. API

54


undefined

undefined : Java
Script- ,
undefined.
, :
var x;
x; // undefined


undefined:
var obj = {};
obj.x; // undefined

undefined

:
function f() {
return;
}
function g() { }
f(); // undefined
g(); // undefined

,
, undefined:
function f(x) {
return x;
}
f(); // undefined

210

undefined ,

54. undefined

. , , , ,
. - ,
JavaScript undefined , ,
, . undefined -
, .
. , highlight
:
element.highlight();

// ,
//
//

element.highlight("yellow");

//
//


?
undefined:
element.highlight(undefined); //
//


undefined.
, ,
. ,
:
var config = JSON.parse(preferences);
// ...
element.highlight(config.highlightColor);
//

, ,
, , -

211

6. API

, , .
undefined,

. API-
:
element.highlight("random");

API ,
,
, .
, undefined, null true. , , :
element.highlight(null);

,
, . , ,

, .

random (
55):
element.highlight({ random: true });

undefined . ,
arguments (. 51)
,
undefined
API-. , -
:
var s1 = new Server(80, "example.com");
var s2 = new Server(80); //
"localhost"

212

Server arguments.length:

54. undefined
function Server(port, hostname) {
if (arguments.length < 2) {
hostname = "localhost";
}
hostname = String(hostname);
// ...
}

,
element.highlight.
, , ,
undefined:
var s3 = new Server(80, config.hostname);

hostname config
,
"localhost",
. "undefined".
undefined, -
-
, undefined:
function Server(port, hostname) {
if (hostname === undefined) {
hostname = "localhost";
}
hostname = String(hostname);
// ...
}


hostname (.3). :
function Server(port, hostname) {
hostname = String(hostname || "localhost");
// ...
}

213

6. API


(||), , , , ,
. , hostname undefined ,
(hostname || "localhost")
"localhost". ,
undefined,
, undefined, . , Server ,
.
API-,
, ,
.
: .
,
,
. , , ,

( NaN, ).
, , ,
:
var c1 = new Element(0, 0); // : 0, : 0
var c2 = new Element();

// : 320, : 240

, ,
:
function Element(width, height) {
this.width = width || 320;

//

this.height = height || 240; //

214

// ...

54. undefined
}
var c1 = new Element(0, 0);
c1.width;

// 320

c1.height; // 240

undefined
:
function Element(width, height) {
this.width = width === undefined ? 320 : width;
this.height = height === undefined ? 240 : height;
// ...
}
var c1 = new Element(0, 0);
c1.width;

// 0

c1.height; // 0
var c2 = new Element();
c2.width;

// 320

c2.height; // 240

undefined ,
.

undefined null
.
, arguments.length
undefined.
,
,
0, NaN .

6. API

55

,
,

53 ,
,
.
.
:
var alert = new Alert(100, 75, 300, 200,
"Error", message,
"blue", "white", "black",
"error", true);

API- .
,
, , ,
,
.
, JavaScript ,
.
, .

:
var alert = new Alert({
x: 100, y: 75,
width: 300, height: 200,
title: "Error", message: message,
titleColor: "blue", bgColor: "white",
textColor: "black",
icon: "error", modal: true

216

});

55. , ,

API- ,
.
: , ,
.
,
: , new Alert,
, true
false .

, ,

. ( ,
,
)
. ,
, position,
size Alert ,
, :
var alert = new Alert(app,
150, 150,
"Error", message,
"blue", "white", "black",
"error", true);

, x y width
height?
:
var alert = new Alert({
parent: app,
width: 150, height: 100,
title: "Error", message: message,
titleColor: "blue", bgColor: "white", textColor:
"black",
icon: "error", modal: true
});

217

6. API


, :
var alert = new Alert(); //
// ,

,
:
var alert = new Alert(app, message, {
width: 150, height: 100,
title: "Error",
titleColor: "blue", bgColor: "white",
textColor: "black",
icon: "error", modal: true
});

, ,
.
:
function Alert(parent, message, opts) {
opts = opts || {}; //
//
this.width = opts.width === undefined ? 320 :
opts.width;
this.height = opts.height === undefined
? 240
: opts.height;
this.x = opts.x === undefined
? (parent.width / 2) - (this.width / 2)
: opts.x;
this.y = opts.y === undefined
? (parent.height / 2) - (this.height / 2)
: opts.y;
this.title = opts.title || "Alert";
this.titleColor = opts.titleColor || "gray";
this.bgColor = opts.bgColor || "white";

218

this.textColor = opts.textColor || "black";

55. , ,
this.icon = opts.icon || "info";
this.modal = !!opts.modal;
this.message = message;
}


, ,
|| (.54). 54
undefined, 0 ,
, .
, ,

, . modal

(!!).
, ,
. ,
,
.
, : .
JavaScript- extend,
.

,
, ,
.
extend Alert :
function Alert(parent, message, opts) {
opts = extend({
width: 320,
height: 240
});
opts = extend({
x: (parent.width / 2) - (opts.width / 2),
y: (parent.height / 2) - (opts.height / 2),

219

6. API
title: "Alert",
titleColor: "gray",
bgColor: "white",
textColor: "black",
icon: "info",
modal: false
}, opts);
this.width = opts.width;
this.height = opts.height;
this.x = opts.x;
this.y = opts.y;
this.title = opts.title;
this.titleColor = opts.titleColor;
this.bgColor = opts.bgColor;
this.textColor = opts.textColor;
this.icon = opts.icon;
this.modal = opts.modal;
}

.
, extend,
, x
y,
width height.
this,
:

220

function Alert(parent, message, opts) {


opts = extend({
width: 320,
height: 240
});
opts = extend({
x: (parent.width / 2) - (opts.width / 2),
y: (parent.height / 2) - (opts.height / 2),
title: "Alert",
titleColor: "gray",
bgColor: "white",
textColor: "black",
icon: "info",
modal: false

55. , ,
}, opts);
extend(this, opts);
}


extend,

, undefined:
function extend(target, source) {
if (source) {
for (var key in source) {
var val = source[key];
if (typeof val !== "undefined") {
target[key] = val;
}
}
}
return target;
}

Alert extend. ,
, ,
. ,
,

,
. .

undefined.
undefined;
|| ,
, .
,
API.

221

6. API

API- ,
.
, ,
.

extend.

56

API-
, - . API-, ,
,

. , ,
:
,
.
, ,
"foo".toUpperCase() "FOO".
Date ,
toString
Date
,
set.

222

,
, API-, , , ,

56.

. API-,
, - Canvas (),

.
fillText:
c.fillText("hello, world!", 75, 25);


, , ,
.
:
c.fillStyle = "blue";
c.font = "24pt serif";
c.textAlign = "center";
c.fillText("hello, world!", 75, 25);

API, ,
:
c.fillText("hello, world!", 75, 25, {
fillStyle: "blue",
font: "24pt serif",
textAlign: "center"
});

? ,
. API-,
, - ,
,
,
, . ,
, , ,
.
,
,
:

223

6. API
c.fillText("text 1", 0, 0);

// ,
//

c.fillStyle = "blue";
c.fillText("text 2", 0, 30);
c.fillStyle = "black";

//

c.fillText("text 3", 0, 60); //


//

API-, ; , , API-
:
c.fillText("text 1", 0, 0);

// ,

//
c.fillText("text 2", 0, 30, { fillStyle: "blue" });
//
c.fillText("text 3", 0, 60); // ,
//

,
: ,
fillText, . , - .
- ,
:
c.fillStyle = "blue";
drawMyImage(c); // drawMyImage -
// c?
c.fillText("hello, world!", 75, 25);

, ,
, drawMyImage. API-,
, ,
,
,
.

224

, API-, , . fillText,

56.

, . ,
,
, . , fillText
. API-,
, , , ,
.
API-, ,
,
.
API-, , .
API-,
,
,
.
INI.
, INI- :
[Host]
address=172.0.0.1
name=localhost
[Connections]
timeout=10000

API
setSection

get:
var ini = INI.parse(src);
ini.setSection("Host");
var addr = ini.get("address");
var hostname = ini.get("name");
ini.setSection("Connection");

225

6. API
var timeout = ini.get("timeout");
var server = new Server(addr, hostname, timeout);

, API-,
, , addr hostname,
:
var ini = INI.parse(src);
var server = new Server(ini.Host.address,
ini.Host.name,
ini.Connection.timeout);

, ini
, , API
. ( -
5.)

API-, .
API-, , , .

57

226

-: -,
, . -

.

57.

HTML-,
. ,

,
,
. :
*,
*.
_,
_.
/, /.

-
:
,
.
,
.
, .

, - , ,
.
, ,
, -, ,
.

.
API-


.
,
-.

227

6. API

,
,
HTML-
-.
- ,
getTitle, getAuthor toHTML.

- ,
.
, MediaWiki (
):
var app = new Wiki(Wiki.formats.MEDIAWIKI);


Wiki:
function Wiki(format) {
this.format = format;
}

,
HTML-, :
Wiki.prototype.displayPage = function(source) {
var page = this.format(source);
var title = page.getTitle();
var author = page.getAuthor();
var output = page.toHTML();
// ...
};

228

, Wiki.formats.MEDIAWIKI? ,
,
Page, -

57.

, Page.
MediaWiki
MWPage, Page, MEDIAWIKI
-, MWPage:
function MWPage(source) {
Page.call(this, source); // //
// ...
}
// MWPage Page
MWPage.prototype = Object.create(Page.prototype);
MWPage.prototype.getTitle = /* ... */;
MWPage.prototype.getAuthor = /* ... */;
MWPage.prototype.toHTML = /* ... */;
Wiki.formats.MEDIAWIKI = function(source) {
return new MWPage(source);
};

(
4.)
Page?
MWPage ,
- (getTitle, getAuthor
toHTML), -
. ,
displayPage

; .
, - .
-
, JavaScript .
MediaWiki :

229

6. API
Wiki.formats.MEDIAWIKI = function(source) {
//
// ...
return {
getTitle: function() { /* ... */ },
getAuthor: function() { /* ... */ },
toHTML: function() { /* ... */ }
};
};

, , . ,
- :
.
, , :
A: **, [], //
B: ****, [[]], **
C: ****, [], **


,
- A, B C. (
!)
, , , ..,

.

230

, Page
- .

JavaScript.
- . displayPage JavaScript- ,
:
getTitle , getAuthor toHTML ,
.

57.

,
, : ,
( ,
...).
, , JavaScript,
- . ,
, ,
. ,

API. , ,

.
. ,
-
HTTP-, -.
, -,
HTTP-,
. , ,
,
,
.

( ).
, .
-, ,
.

6. API

58

API- .
:
var bits = new BitVector();
bits.enable(4);
bits.enable([1, 3, 8, 17]);
bits.bitAt(4); // 1
bits.bitAt(8); // 1
bits.bitAt(9); // 0

enable:
, .
API-
:
var set = new StringSet();
set.add("Hamlet");
set.add(["Rosencrantz", "Guildenstern"]);
set.add({ "Ophelia": 1, "Polonius": 1, "Horatio": 1
});
set.contains("Polonius");
// true
set.contains("Guildenstern"); // true
set.contains("Falstaff");

// false

enable ,
add ,
-.
BitVector.prototype.enable , ,
, :

232

BitVector.prototype.enable = function(x) {
if (typeof x === "number") {

58.
this.enableBit(x);
} else { // , x
//
for (var i = 0, n = x.length; i < n; i++) {
this.enableBit(x[i]);
}
}
};

. StringSet.prototype.add?
- .
,
JavaScript !
,
.
, JavaScript ,
(.51).
, .
,
, . , , length,
,
. -, "length"?
dimensions.add({
"length": 1, // ,
// ?
"height": 1,
"width": 1
});


.

(
, 57),
.
,

233

6. API

,
.
, ,
. , , .
.
API-
- .

StringSet , , ,
. ,
, , ,
. ,
instanceof
Array.
prototype:
StringSet.prototype.add = function(x) {
if (typeof x === "string") {
this.addString(x);
} else if (x instanceof Array) { //

//

x.forEach(function(s) {
this.addString(s);
}, this);
} else {
for (var key in x) {
this.addString(key);
}
}
};

234

, , Array, .

58.

, .
, ,

Array -. ,

. Array.prototype
.
ES5 Array.
isArray, , .
ECMAScript , [[Class]] "Array".
, ,
, Array.
isArray , instanceof.
add:
StringSet.prototype.add = function(x) {
if (typeof x === "string") {
this.addString(x);
} else if (Array.isArray(x)) {
//
x.forEach(function(s) {
this.addString(s);
}, this);
} else {
for (var key in x) {
this.addString(key);
}
}
};

, ES5,
Object.prototype.toString:
var toString = Object.prototype.toString;
function isArray(x) {
return toString.call(x) === "[object Array]";
}

235

6. API

Object.prototype.toString

[[Class]],

, instanceof.
, add -,
API. API-
, .
, ,
, :
function MyClass() {
this.keys = new StringSet();
// ...
}
MyClass.prototype.update = function() {
this.keys.add(arguments); //
//
};

add , ,
51:
MyClass.prototype.update = function() {
this.keys.add([].slice.call(arguments));
};

API- , ,
API ,
. ,
API-. ,
, enable ,
, add ,
, .

236

59.

- .

.

, , .
, API-,
, .
ES5 Array.isArray.

59

JavaScript, ,
(.3). ,

.
,
:
function square(x) {
return x * x;
}
square("3"); // 9

,
. , 3,
,

.

237

6. API


, enable 58.
,
. ,
enable .
?
:
BitVector.prototype.enable = function(x) {
x = Number(x);
if (typeof x === "number") { // true
this.enableBit(x);
} else {
//
//
for (var i = 0, n = x.length; i < n; i++) {
this.enableBit(x[i]);
}
}
};


,
.
, .
:
bits.enable("100"); // ?

238

enable : , , ,
. , -
. ,
, API. ,
API- ,

:

59.
BitVector.prototype.enable = function(x) {
if (typeof x === "number") {
this.enableBit(x);
} else if (typeof x === "object" && x) {
for (var i = 0, n = x.length; i < n; i++) {
this.enableBit(x[i]);
}
} else {
throw new TypeError("
");
}
}

enable
,
, .
. ,
, x
, length,
, ,
String. JavaScript
, typeof,
. ,
BitVector
:
function BitVector(x) {
uint32.or(arrayLike).guard(x);
// ...
}

,
-, guard:
var guard = {
guard: function(x) {
if (!this.test(x)) {

239

6. API
throw new TypeError(" " + this);
}
}
};



:
var uint32 = Object.create(guard);
uint32.test = function(x) {
return typeof x === "number" && x === (x >>> 0);
};
uint32.toString = function() {
return "uint32";
};

uint32
JavaScript-
32- .

32-
(.2).
. , uint32.test
32- .
arrayLike:
var arrayLike = Object.create(guard);
arrayLike.test = function(x) {
return typeof x === "object" && x &&
uint32.test(x.length);
};
arrayLike.toString = function() {
return "array-like object";
};

240

, , , -

59.

, ,
length.
,
- (.60), ,
or:
guard.or = function(other) {
var result = Object.create(guard);
var self = this;
result.test = function(x) {
return self.test(x) || other.test(x);
};
var description = this + " or " + other;
result.toString = function() {
return description;
};
return result;
};

-
(, this)
( other), ,
test toString
. ,
self,
this (.25 37) test, .
,
, .

. ,
( ,
) ( , ,
).

241

6. API

.
.

60

API-, (.56),

.
replace.
, , replace
.

HTML-:
function escapeBasicHTML(str) {
return str.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&apos;");
}

242

replace ,
"&" HTML
"&amp;", "<" "&lt;" ..

.

60.

,
,
:
function escapeBasicHTML(str1) {
var str2 = str1.replace(/&/g, "&amp;");
var str3 = str2.replace(/</g, "&lt;");
var str4 = str3.replace(/>/g, "&gt;");
var str5 = str4.replace(/"/g, "&quot;");
var str6 = str5.replace(/'/g, "&apos;");
return str6;
}


,
, ,
.
,
API - (.57)
, , .
, 50 51,
API :
var users = records.map(function(record) {
return record.username;
})
.filter(function(username) {
return !!username;
})
.map(function(username) {
return username.toLowerCase();
});

,
,
, ,
,
.

243

6. API

API
,
API-.
API-, ,

: API- , .
API-,
.
, .
,
, this undefined.

:
element.setBackgroundColor("yellow")
.setColor("red")
.setFontWeight("bold");

244

API-,
, . ( , Smalltalk,

.)
this, API .
,
, , , ,

. jQuery
, (
), -
,
( ), :

60.
$("#notification")

//
//

.html(" .") //
//
.removeClass("info")

//
//

.addClass("error");

//
//


html, removeClass addClass , ,

, jQuery- ($).
, , ,
:
var element = $("#notification");
element.html(" .");
element.removeClass("info");
element.addClass("error");

API ,
.
undefined, .

, , .
, , , , .
, ,
this.

7.

JavaScript
. JavaScript-
,
. , , -.
,
-, :
,
, ,
, .
-
.

.

246

JavaScript ,
,
;
,
, , , , API-.
,
, JavaScript
-, JavaScript
,
,
, Node.js.

61. -

,
ECMAScript
. ,
,
JavaScript, . JavaScript-
,
, . , ,
API-
JavaScript.

61

JavaScript- :

, ( ,
), , ,
.
, :
var text = downloadSync("http://example.com/file.txt");
console.log(text);

(API console.log JavaScript-,


.) , downloadSync,
, :

,
.
,
:

247

7.

.
()
,
.
JavaScript - , ,
API-.
(.19),
:
downloadAsync("http://example.com/file.txt",
function(text) {
console.log(text);
});

, API- ,
. , ,
,
.

, , .
JavaScript ,

(run-to-completion):
, , -
-,
.
,
.

248

.7.1 .
( ). JavaScript-
,

61. -

, ,
, JavaScript- (
, ,
downloadAsync),
.

. 7.1. :
-; -

249

7.

,
: , - ,
, - .
, JavaScript,
, ,
, C++, Java C#.
,
.
, ,

,
, .

,
.

JavaScript API- - . API ,
, , .
XMLHttpRequest, -,
downloadAsync, ,
. -

,
, -.

250

API- , ,
, .
, URL- .

61. -

.

,
JavaScript-,
. JavaScript-

, .
,
, . , -
API- Worker (),
.
,
-
,
,
.
XMLHttpRequest
;
,
. API-
,
, .
API-
, .


API-
.
JavaScript ,
, .
- .

7.

62

61 , API- -
,
.
, ,
. ,
"starting" "finished",

:
downloadAsync("file.txt", function(file) {
console.log("finished");
});
console.log("starting");

downloadAsync ,
. , JavaScript
, - .
, "starting"
"finished".

252


, , API , .
"starting".
-
,
"finished".

62.

, - ,

, ? ,
URL- ,
URL-?
:
db.lookupAsync("url", function(url) {
// ?
});
downloadAsync(url, function(text) { // : url

console.log(" " + url + ": " + text);


});

, ,
URL-,
, downloadAsync , .
: ,
,
.

.
(.11) :
db.lookupAsync("url", function(url) {
downloadAsync(url, function(text) {
console.log(" " + url + ": " + text);
});
});

,
, ,
.
,
url.

253

7.

,
, :
db.lookupAsync("url", function(url) {
downloadAsync(url, function(file) {
downloadAsync("a.txt", function(a) {
downloadAsync("b.txt", function(b) {
downloadAsync("c.txt", function(c) {
// ...
});
});
});
});
});


,

. :
db.lookupAsync("url", downloadURL);
function downloadURL(url) {
downloadAsync(url, function(text) {
// -
showContents(url, text);
});
}
function showContents(url, text) {
console.log(" " + url + ": " + text);
}


downloadURL, url text showContents.
bind (.25):

254

db.lookupAsync("url", downloadURL);
function downloadURL(url) {

62.
downloadAsync(url, showContents.bind(null, url));
}
function showContents(url, text) {
console.log(" " + url + ": " + text);
}

,

.
, :
db.lookupAsync("url", downloadURLAndFiles);
function downloadURLAndFiles(url) {
downloadAsync(url, downloadABC.bind(null, url));
}
//
function downloadABC(url, file) {
downloadAsync("a.txt",
//
downloadFiles23.bind(null, url,
file));
}
//
function downloadBC(url, file, a) {
downloadAsync("b.txt",
//
downloadFile3.bind(null, url,
file, a));
}
//
function downloadC(url, file, a, b) {
downloadAsync("c.txt",
//

finish.bind(null, url, file, a, b));


}
function finish(url, file, a, b, c) {
// ...
}

255

7.

,
,
:
db.lookupAsync("url", function(url) {
downloadURLAndFiles(url);
});
function downloadURLAndFiles(url) {
downloadAsync(url, downloadFiles.bind(null, url));
}
function downloadFiles(url, file) {
downloadAsync("a.txt", function(a) {
downloadAsync("b.txt", function(b) {
downloadAsync("c.txt", function(c) {
// ...
});
});
});
}

,

:
function downloadFiles(url, file) {
downloadAllAsync(["a.txt", "b.txt", "c.txt"],
function(all) {
var a = all[0], b = all[1], c = all[2];
// ...
});
}

256

downloadAllAsync
. ,
,
.
, URL-,
,
.

63.

, , ,
,
. 66 , ,
downloadAllAsync.

,
. 68
.
,
.


.


.
,
.

63

.

, try:
try {
f();
g();
h();

257

7.
} catch (e) {
// ...
}

,
,
, try
. ,
API- ,
,
, !
API-

, . , API-
, ,
61, ,
:
downloadAsync("http://example.com/file.txt",
function(text) {
console.log(" : " + text);
}, function(error) {
console.log(": " + error);
});


, 62:
downloadAsync("a.txt", function(a) {
downloadAsync("b.txt", function(b) {
downloadAsync("c.txt", function(c) {
console.log(": " + a + b + c);
}, function(error) {
console.log(": " + error);
});
}, function(error) { //
//

258

console.log(": " + error);

63.
});
}, function(error) { //
//
console.log(": " + error);
});

,

, . ,
.
,
:
function onError(error) {
console.log(": " + error);
}
downloadAsync("a.txt", function(a) {
downloadAsync("b.txt", function(b) {
downloadAsync("c.txt", function(c) {
console.log(": " + a + b + c);
}, onError);
}, onError);
}, onError);

,

, downloadAllAsync ( 62 66),

,
:
downloadAllAsync(["a.txt", "b.txt", "c.txt"],
function(abc) {
console.log(": " + abc[0] + abc[1] +
abc[2]);
}, function(error) {
console.log(": " + error);
});

259

7.

API , Node.js, ,
, ,
, , ,
null. API- -
,

if:
function onError(error) {
console.log(": " + error);
}
downloadAsync("a.txt", function(error, a) {
if (error) {
onError(error);
return;
}
downloadAsync("b.txt", function(error, b) {
//

if (error) {
onError(error);
return;
}
downloadAsync(url3, function(error, c) {
//

if (error) {
onError(error);
return;
}
console.log(": " + a + b + c);
});
});
});

260

, , ,
,

63.

if
, ,
:
function onError(error) {
console.log(": " + error);
}
downloadAsync("a.txt", function(error, a) {
if (error) return onError(error);
downloadAsync("b.txt", function(error, b) {
if (error) return onError(error);
downloadAsync(url3, function(error, c) {
if (error) return onError(error);
console.log(": " + a + b + c);
});
});
});

, , :
var filenames = ["a.txt", "b.txt", "c.txt"];
downloadAllAsync(filenames, function(error, abc) {
if (error) {
console.log(": " + error);
return;
}
console.log(": " + abc[0] + abc[1] +
abc[2]);
});

try...
catch
API- , try ,
.
API-, , ,

- .
-

261

7.

. , ,
:
(
,
). , ,
.
: API-
,
.

,
.
, ,
.

64

, URL ,
. API- ,
:
function downloadOneSync(urls) {
for (var i = 0, n = urls.length; i < n; i++) {
try {
return downloadSync(urls[i]);
} catch (e) { }
}
throw new Error(" ");

262

64.

downloadOneAsync,
.
,
,

:
function downloadOneAsync(urls, onsuccess, onerror) {
for (var i = 0, n = urls.length; i < n; i++) {
downloadAsync(urls[i], onsuccess,
function(error) {
// ?
});
//
}
throw new Error(" ");
}

, -,
, . , ,
:
function downloadOneAsync(urls, onsuccess, onfailure)
{
var n = urls.length;
function tryNextURL(i) {
if (i >= n) {
onfailure("
");
return;
}
downloadAsync(urls[i], onsuccess, function() {
tryNextURL(i + 1);
});
}
tryNextURL(0);
}

263

7.

tryNextURL :
. JavaScript- ,
,
. ,
100000 ,
JavaScript-
:
function countdown(n) {
if (n === 0) {
return "";
} else {
return countdown(n 1);
}
}
countdown(100000); // :


downloadOneAsync,
n countdown ?
,
countdown.
JavaScript-
, ,
, .
:
function negative(x) {
return abs(x) * -1;
}
function abs(x) {
return Math.abs(x);
}
console.log(negative(42));

264

, Math.abs 42, -

64.

,
. 7.2
.
,
.
, ,
: ,
(
), .
Math.abs ,
abs ,
negative, , , .

( )
negative(42)
abs(42)
Math.abs(42)

console.log();
return times(, -1);
return ;
[built-in code]

. 7.2.

,
, .
.
countdown(100000)
countdown 100000 ,
,
.7.3. ,
, , JavaScript-,
.

265

7.

( )

console.log();

countdown(100000)

return countdown();

countdown(99999)

return countdown();

countdown(99998)

return countdown();
.
.
.

countdown(1)

return countdown();

countdown(0)

return "done";

. 7.3.

downloadOneAsync.
countdown, ,
, downloadOneAsync
. , API-
,
. ,
downloadOneAsync , , ,

. (,
,
.) , downloadOneAsync
,
, .

266

65.

.

.
,
, .

65

61 , API-

. .
, ,

:
while (true) { }


.
,
. ,
,
JavaScript.
.

,

.
, ,

267

7.

,
.
, ,
JavaScript-

.
, ,
? ,
. ,
,
API- Worker.
,
.

:
var ai = new Worker("ai.js");


, ai.js.
:
- .

.
,
:
var userMove = /* ... */;
ai.postMessage(JSON.stringify({
userMove: userMove
}));

268

, postMessage, .

:

65.
ai.onmessage = function(event) {
executeMove(JSON.parse(event.data).computerMove);
};

ai.js
, :
self.onmessage = function(event) {
//
var userMove = JSON.parse(event.data).userMove;
//
var computerMove = computeNextMove(userMove);
//
var message = JSON.stringify({
computerMove: computerMove
});
self.postMessage(message);
};
function computeNextMove(userMove) {
// ...
}

API-, Worker ,
JavaScript-.
.

, .
48 :
Member.prototype.inNetwork = function(other) {
var visited = {};
var worklist = [this];
while (worklist.length > 0) {
var member = worklist.pop();
// ...
if (member === other) { // ?
return true;
}
// ...

269

7.
}
return false;
};

while, ,
,

. API- ,

,
,
,

.
,
: while .
inNetwork ,
64, while
:
Member.prototype.inNetwork = function(other, callback)
{
var visited = {};
var worklist = [this];
function next() {
if (worklist.length === 0) {
callback(false);
return;
}
var member = worklist.pop();
// ...
if (member === other) { // ?
callback(true);
return;
}
// ...
setTimeout(next, 0); //
//

270

65.
setTimeout(next, 0); //
//
};

.
while
next, ,

. , ,
.
- , , ,

, next
- .
API setTimeout, JavaScript, next ( 0 ).

. ,
setTimeout
. , -
4,
postMessage,
.
,
,

. ,
next:
Member.prototype.inNetwork = function(other, callback)
{
// ...
function next() {

271

7.
for (var i = 0; i < 10; i++) {
// ...
}
setTimeout(next, 0);
}
setTimeout(next, 0);
};

.
, API- Worker,

.
API- Worker
,
.

66

63 downloadAllAsync, URL-, , URL-.


, downloadAllAsync
:
,
.

272

.
:

66.
function downloadAllAsync(urls, onsuccess, onerror) {
var result = [], length = urls.length;
if (length === 0) {
setTimeout(onsuccess.bind(null, result), 0);
return;
}
urls.forEach(function(url) {
downloadAsync(url, function(text) {
if (result) {
//
result.push(text);
if (result.length === urls.length) {
onsuccess(result);
}
}
}, function(error) {
if (result) {
result = null;
onerror(error);
}
});
});
}

,
, .
, , ,
,

, forEach .
(67 , setTimeout
onsuccess
, .) URL-,
.
;
URL- ,
onsuccess -

273

7.

. - ,
onerror
.

null,
onerror .
, ,
:
var filenames = [
"huge.txt",

//

"tiny.txt",

//

"medium.txt" //
];
downloadAllAsync(filenames, function(files) {
console.log(" : " + files[0].length);
//
console.log(" : " + files[1].length);
//
console.log(" : " + files[2].length);
//
}, function(error) {
console.log(" : " + error);
});

274

,
(, ,
). , , tiny.
txt , medium.txt huge.txt, , downloadAllAsync,
, .
downloadAllAsync

. , downloadAllAsync
, ,
.
API- ,

66.

,
. ,
,
, ,
.
48 :
, .
JavaScript. , ,
, ,
.
, ,
:

- , . (

, .)
:
,
-. ,
downloadAllAsync
, ,
, :
downloadAllAsync(filenames, function(files) {
console.log(" : " + files[2].length);
console.log(" : " + files[0].length);
console.log(" : " + files[1].length);
}, function(error) {
console.log(": " + error);
});


,
-

275

7.

-
. ,
, ,
. , , , .
downloadAllAsync ,
.
,
:
function downloadAllAsync(urls, onsuccess, onerror) {
var length = urls.length;
var result = [];
if (length === 0) {
setTimeout(onsuccess.bind(null, result), 0);
return;
}
urls.forEach(function(url, i) {
downloadAsync(url, function(text) {
if (result) {
result[i] = text;
//
//
if (result.length === urls.length) {
onsuccess(result);
}
}
}, function(error) {
if (result) {
result = null;
onerror(error);
}
});
});
}

276

66.

forEach,
. ,
. 51 :
,
length .
:
downloadAllAsync(["huge.txt", "medium.txt", "tiny.
txt"]);

tiny.txt ,
2, result.length 3.


.
,
:
function downloadAllAsync(urls, onsuccess, onerror) {
var pending = urls.length;
var result = [];
if (pending === 0) {
setTimeout(onsuccess.bind(null, result), 0);
return;
}
urls.forEach(function(url, i) {
downloadAsync(url, function(text) {
if (result) {
result[i] = text;
//
pending--;
//
if (pending === 0) {
onsuccess(result);
}

277

7.
}
}, function(error) {
if (result) {
result = null;
onerror(error);
}
});
});
}

, ,
pending ,
,
.

JavaScript- ,
.
, .

67

downloadAsync, ( Dict
.45)
. , ,
:
var cache = new Dict();

278

function downloadCachingAsync(url, onsuccess, onerror)

67.
{
if (cache.has(url)) {
onsuccess(cache.get(url)); //
return;
}
return downloadAsync(url, function(file) {
cache.set(url, file);
onsuccess(file);
}, onerror);
}

,

API-. . 62 , API-
:
downloadAsync("file.txt", function(file) {
console.log("finished");
});
console.log("starting");

downloadCachingAsync, , ,
:
downloadCachingAsync("file.txt", function(file) {
console.log("finished"); //
});
console.log("starting");


. API-
.
61,
, -

279

7.

, .
, ,
, , ,
.
, ,
,
:
downloadCachingAsync(remaining[0], function(file) {
remaining.shift();
// ...
});
status.display(" " + remaining[0] + "...");

,
(, , "undefined",
).
. 64
,

,
, .
,

. :
downloadCachingAsync,
, , ,
, .

280


, API- -

67.

. , 65 66

-, setTimeout.
,
,
setTimeout:
var cache = new Dict();
function downloadCachingAsync(url, onsuccess, onerror)
{
if (cache.has(url)) {
var cached = cache.get(url);
setTimeout(onsuccess.bind(null, cached), 0);
return;
}
return downloadAsync(url, function(file) {
cache.set(url, file);
onsuccess(file);
}, onerror);
}

bind (.25),

onsuccess.

, .

.

.

API-,
setTimeout.

7.

68


API-
(promises),
(deferreds), (futures).
API-
:
downloadAsync("file.txt", function(file) {
console.log(": " + file);
});

API-, ,
, ,

then:
var p = downloadP("file.txt");
p.then(function(file) {
console.log(": " + file);
});


.
(composability).
, then, (
), .

:
var fileP = downloadP("file.txt");
var lengthP = fileP.then(function(file) {

282

return file.length;

68.
});
lengthP.then(function(length) {
console.log(": " + length);
});

,

, ,
. then , , ,
,
.
, , . ,

:
var filesP = join(downloadP("file1.txt"),
downloadP("file2.txt"),
downloadP("file3.txt"));
filesP.then(function(files) {
console.log("1: " + files[0]);
console.log("2: " + files[1]);
console.log("3: " + files[2]);
});

when, :
var fileP1 = downloadP("file1.txt"),
fileP2 = downloadP("file2.txt"),
fileP3 = downloadP("file3.txt");
when([fileP1, fileP2, fileP3], function(files) {

283

7.
console.log("1: " + files[0]);
console.log("2: " + files[1]);
console.log("3: " + files[2]);
});


- ,
then

, join,

. , , , 66.
,
:
var file1, file2;
downloadAsync("file1.txt", function(file) {
file1 = file;
});
downloadAsync("file2.txt", function(file) {
file1 = file; //
});

,
.

284

,
,
, 62.
, .
,
,

68.

, ,
, , 63.
,
,
. ,
, , .
select ( choose)
,
. , :
var fileP =
select(downloadP("http://example1.com/file.txt"),
downloadP("http://example2.com/file.txt"),
downloadP("http://example3.com/file.
txt"));
fileP.then(function(file) {
console.log(": " + file);
});

select
-
, :
var fileP = select(downloadP("file.txt"),
timeoutErrorP(2000));
fileP.then(function(file) {
console.log(": " + file);
}, function(error) {
console.log(" -
-: " + error);
});

285

7.

then
.

,
, .

.
API- ,
.
select (
choose) ,
.

286

JavaScript. 68
JS
.

.
.

, 192102, -, . (. ),
. 3, , . 7.
005-93,
2; 95 3005 .
26.04.13. 70100/16. . . . 23,220.
2000.
CtP
. 194044, -, . , 9.
/ (812) 495-56-10.

?
!
?
?
? ,

?
!


!

www.piter.com/ePartners

www.piter.com,
,

( www.piter.com)
!
.
10% ,
, - c
. ,
, 5%
.
, , 500 ,
. Web.Money.
:
http://www.piter.com/book.phtml?978538800282
http://www.piter.com/book.phtml?978538800282&refer=0000
, 0000


WWW.PITER.COM