Открыть Электронные книги
Категории
Открыть Аудиокниги
Категории
Открыть Журналы
Категории
Открыть Документы
Категории
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
15
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;
// ""
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
, 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
// 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
// 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
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)
. (".")
:
/^.$/.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");
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
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");
f("bananas");
, 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");
hamAnd("mustard");
turkeyAnd("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;
}
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
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"
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
// ?
.
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
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]);
:
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
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
31. Object.getPrototypeOf
31
Object.
getPrototypeOf,
__proto__
"__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- . ( ,
,
, "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.
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"
"Boolean"
new Boolean(...)
"Date"
new Date(...)
"Error"
"Function"
"JSON"
JSON
"Math"
Math
"Number"
new Number(...)
"Object"
"RegExp"
"String"
// "[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.
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) {
//
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 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
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
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;
//
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
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
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";
//
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, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
242
replace ,
"&" HTML
"&", "<" "<" ..
.
60.
,
,
:
function escapeBasicHTML(str1) {
var str2 = str1.replace(/&/g, "&");
var str3 = str2.replace(/</g, "<");
var str4 = str3.replace(/>/g, ">");
var str5 = str4.replace(/"/g, """);
var str6 = str5.replace(/'/g, "'");
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);
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
, ,
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",
//
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
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
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
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