Сила javascript. 68 Способов Эффективного Использования js
TRANSCRIPT
-
32.988.02-018.1 004.43 39
.39 JavaScript. 68 JS.
.: , 2013. 288 .: . ( -).
ISBN 978-5-496-00524-1
- JavaScript -. - , - , JavaScript .
68 JavaScript, . , - , -, JavaScript.
12+ ( 12 . 29 2010 . 436-.)
32.988.02-018.1 004.43
Addison-Wesley Longman. . - ., , , - . , , - , .
ISBN 978-0321812186 .ISBN 978-5-496-00524-1 Pearson Education, Inc. , 2013 , , 2013
-
5
. . . . . . . . . . . . . . . . . . . . . . . . . . .9
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 12JavaScript ECMAScript . .. .. .. .. .. .. .. .. .. .. .. .. .. .. 13- . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 13 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 14
. . . . . . . . . . . . . . . . . . . . . . . . . 15
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1. JavaScript . . . . . . . . . . . . . . . . . . . . . .19
1. , JavaScript . .. .. 202. .. .. .. .. .. .. .. .. .. 283. .. .. .. .. 324. ,
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 405. ==
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 426.
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 467.
16- . .. .. .. .. .. .. .. 55
-
6
2. . . . . . . . . .618.
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 619. . .. .. .. .. .. .. .. .. .. 6510. with .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 6711. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 7212. .. .. .. .. .. .. .. .. .. .. .. .. 7613.
- .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 79
14. , - .. .. .. .. .. .. .. .. .. .. .. .. .. 83
15. , - .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 88
16. eval . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 91
17. eval .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 93
3. . . . . . . . . . . . . . .9618. ,
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. 9619.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .10020. call
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .10521. apply
.. .. .. .. .. .. .. .. .. .. .. .. .. .10722. arguments
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .11023. arguments . .. .. .11224.
arguments . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .11525. bind
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .11726. bind . .. .12027.
, .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .122
-
7
28. toString . .. .. .12429.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .127
4. . . . . . . . . . . . . . . . 13030.
prototype, getPrototypeOf __proto__ .. .. .. .. .. .. .. .. .. .. .. .13131.
Object.getPrototypeOf, __proto__ . .. .. .. .. .. .13532. __proto__ . .. .13633. ,
new .. .. .. .. .. .. .. .13834. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .14235.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .14436.
- .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .14737. this.. .. .. .. .. .. .. .. .. .15038.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .15439. .. .15940. .. .. .. .. .16141. .. .. .. .. .. .. .. .16442.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .166
5. . . . . . . . . . . . . . . . . . 16943.
. .. .. .. .. .. .. .16944. null
.. .. .. .. .17345. hasOwnProperty
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .17646. ,
.. .. .. .. .. .. .18247.
Object.prototype .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .18648. 18849.
for, for...in . .. .194
-
8
50. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .196
51. Array , . .. .202
52. , Array .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .205
6. API . . . . . . . . . . . 20753. .. .. .. .. .. .. .. .20754. undefined . .21055. , ,
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .21656. .. .. .. .. .. .. .. .. .22257.
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .22658. . .. .. .. .. .. .. .. .. .. .. .23259. . .. .. .23760. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .242
7. . . . . . . . . . . . . . . . . . . . . . 24661. - . .. .. .24762.
. .. .. .. .. .. .. .. .. .. .. .. .. .252
63. . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .257
64. .. .. .. .. .26265. . .. .. .. .. .26766.
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .27267.
. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .27868.
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .282
-
9
, JavaScript 1995 , , - Java, , , Netscape , .
, - ( , -), , , JavaScript - . , , , , - . , , , - , , JavaScript .
, , - . - (,
-
10
). (monkey-patching), , ( , - spackle).
, , , JavaScript, - . - , : Prototype Ruby, MochiKit Python, Dojo Java, TIBET Smalltalk. JavaScript - jQuery (JavaScript ), , 2007 , . - - JavaScript-, , .
JavaScript , , , -.
JavaScript - ( ) , , , - ECMAScript - , , ,
-
11
. JavaScript . - , JavaScript . , ( ), , .
, , JavaScript - (, !). , , - , JavaScript- , - . , , , , , .
- , - . , - , JavaScript-, - . , , - .
, 2006 , Mozilla - - Ecma. , , . !
(Brendan Eich)
-
12
, , , , . , , , . - , , , JavaScript.
JavaScript. - , , JavaScript . , - JavaScript, (Douglas Crockford), JavaScript: The Good Parts (Marijn Haverbeke) Eloquent JavaScript. - , JavaScript , .
-
13
-
JavaScript EcMaScript
- . , JavaScript. , , , - ECMAScript. , : - , Ecma International, JavaScript. , ECMA (European Computer Manufacturers Association) Ecma International, , - (ECMAScript), .
, ECMAScript, , Ecma. , JavaScript - , , , - -. . ECMAScript, JavaScript. - ES5 ECMAScript.
-
JavaScript, --. JavaScript - ,
-
14
- , . , , Node.js, JavaScript - . -, JavaScript, -. , - , , , API- - -.
JavaScript , . , ECMAScript JavaScript- . 7, - JavaScript - . JavaScript- -. JavaScript, . , JavaScript ECMAScript.
-
15
- JavaScript (Brendan Eich). - JavaScript Mozilla.
, , - -. (Ben) cowboy (Alman), (Erik Arvidsson), (Mathias Bynens), (Tim) creationix (Caswell), (Michaeljohn) inimino (Clement), (Angus Croll), (Andrew Dupont), (Ariya Hidayat), (Steven Levithan), (Pan Thomakos), (Jeff Walden) (Juriy) kangax (Zaytsev). , ECMAScript, , - Edition5, - - (Allen Wirfs-Brock). Mozilla Developer Network API- .
. (John Resig) , , .
-
16
(Blake Kaplan) (Patrick Walton) - . (Brian Anderson), (Norbert Lindenberg), - (Sam Tobin-Hochstadt), (Rick Waldron) (Patrick Walton).
- Pearson. (Olivia Basegio), (Audrey Doyle), (Trina MacDonald), (Scott Meyers) (Chris Zahn) , . .
, - -. , (Erik Arvidsson), (Rebecca Murphey), (Rick Waldron) (Richard Worth), . .
-, . . , , (Andy Denmark), (Rick Waldron) (Travis Winfrey) .
Java Beach -. . - .
, . , . (, .)
-
17
2006, .
. , - , , , . , , .
, , , (Lisa Silveria), .
-
18
Mozilla Research. - , , - ( ) - . Ecma TC39, , - JavaScript.
-
19
1.
JavaScript
JavaScript . , Java, , ( , , -), JavaScript , - . - , , .
JavaScript - , - . JavaScript, .
-
1 . JavaScript
20
1 , JavaScript
, JavaScript . - Java - -, JavaScript Java -. JavaScript 1997 , ECMAScript. - JavaScript, ECMAScript.
ECMAScript ( - ES3), 1999, JavaScript. ES5 (Edition5), 2009. ES5 - , , , , . ES5 , , ES5, .
, , - - JavaScript. , JavaScript- const, ECMAScript - . , const . , const, :
-
1 . , JavaScript
21
const PI = 3.141592653589793;PI = "!";
PI; // 3.141592653589793
const - var:
const PI = 3.141592653589793;PI = "!";PI; // "!"
- - JavaScript, - . , - JavaScript - - JavaScript . -, - .
JavaScript - - . , . JavaScript. - - JavaScript .
- JavaScript. , . - , -, . ,
-
1 . JavaScript
22
, . , const , - , --, .
ES5 . JavaScript, -, - . , , - , . :
"use strict";
, :
function f(x) { "use strict"; // ...}
- , : , ES3 . , JavaScript-, : , -
-
1 . , JavaScript
23
. 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() {
-
1 . JavaScript
24
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() { // //
// ...}// ...
-
1 . , JavaScript
25
- , , , .
, - , , .
, , , , , . , , , , .
, - - (Immediately Invoked Function Expression, IIFE).
13, , - - . :
//
(function() { // file1.js "use strict"; function f() { // ... } // ...})();
-
1 . JavaScript
26
(function() { // file2.js //
function f() { var arguments = []; // ... } // ...})();
, ( ) . - . , var function ( 8). , , - . , , .
, .
, - , , - , , . - , - ,
-
1 . , JavaScript
. , IIFE, IIFE , , - , :
(function() { "use strict"; function f() { // ... } // ...})();
, , - -. , , , , -. , , , .
, JavaScript - .
, JavaScript , .
, , - , .
, - - .
-
1 . JavaScript
28
2
- , JavaScript . typeof, :
typeof 17; // ""
typeof 98.6; // ""
typeof -2.1; // ""
JavaScript , 64-- , IEEE754, doubles ( ). -, , , - 53. 9007199254740992 (253) 9007199254740992 (253) . , JavaScript .
- , :
0.1 * 1.9 // 0.19-99 + 100; // 121 - 12.3; // 8.72.5 / 5; // 0.521 % 8; // 5
- . , 32--
-
2 .
29
. (, 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. -
-
1 . JavaScript
30
parseInt, 2:
parseInt("1001", 2); // 9
( , .)
- , - , , JavaScript . , JavaScript- : , , . , , , - .
, - : , , , . , , , . , , :
0.1 + 0.2; // 0.30000000000000004
64- -, , . , .
-
2 .
31
, , . - , . , - , , x, y z :
(x + y) + z = x + (y + z).
- :
(0.1 + 0.2) + 0.3; // 0.60000000000000010.1 + (0.2 + 0.3); // 0.6
- . , , . , , .
, , - , . - . , , , :
(10 + 20) + 30; // 6010 + (20 + 30); // 60
, , , 253 253. .
-
1 . JavaScript
32
JavaScript . JavaScript ,
.
, 32- .
, - .
3
, JavaScript , . :
3 + true; // 4
, true . . - , . JavaScript , 4!
JavaScript. , , - null:
"hello"(1); // :
null.x; // : // 'x' null
-
3 .
33
, - , 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"
-
1 . JavaScript
34
, , 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
, isNaN , , -
-
3 .
35
. ( isNaN, , coercesToNaN, NaN.) , , - NaN isNaN:
isNaN(NaN); // true
, - NaN, NaN, NaN:
isNaN("foo"); // trueisNaN(undefined); // trueisNaN({}); // trueisNaN({ valueOf: "foo" }); // true
, NaN , - . NaN JavaScript-, , NaN - :
var a = NaN;a !== a; // true
var b = "foo";b !== b; // false
var c = undefined;c !== c; // false
var d = {};d !== d; // false
var e = { valueOf: "foo" };
e !== e; // false
:
function isReallyNaN(x) { return x !== x;
}
-
1 . JavaScript
36
, - , .
, , - . , , , , - . - , , . , , , .
. :
"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"
2 * { valueOf: function() { return 3; } }; // 6
-
3 .
37
, + , - . , , 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().
-
1 . JavaScript
38
- . , 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; }
-
3 .
39
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, .
-
1 . JavaScript
40
4 ,
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");s1 === s2; // false
-
4 . ,
41
String - , . :
s1 == s2; // false
- , . . JavaScript : , , - . , String toUpperCase, . :
"hello".toUpperCase(); // "HELLO"
- , - :
"hello".someProperty = 17;"hello".someProperty; // undefined
String, . , JavaScript . , , - JavaScript , - : , , . .
-
1 . JavaScript
42
, .
.
5 ==
, -:
"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()) { // !
// ...}
-
5 . ==
43
, 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 -
-
1 . JavaScript
==, -. , null == undefined, undefined == null. , - . , valueOf toString, - . Date, .
1.1. ==
1 2
null undefined ; true
null undefined , null
undefined
; false
,
Date => , Date
=> (
toString, valueOf)
,
, -
Date
=> , ,
Date=>
( valueOf,
toString)
,
,
=>
-
5 . ==
45
, == . , . - . 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
-
1 . JavaScript
46
, , - ==, , , .
== .
, - , === .
, - .
6
, JavaScript, - , -. , :
function Point(x, y) { this.x = x || 0 this.y = y || 0}
Point.prototype.isOrigin = function() { return this.x === 0 && this.y === 0}
-
6 .
47
, , - . 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 } //
-
1 . JavaScript
48
:
, .
, - .
:
a = b(f());
-, :
a = b(f());
. - :
a = bf();
, :
a = b f();
: , , . , -.
-: (, [, +, - /. , -
-
6 .
49
, . , , -. , . , , , , - , . :
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.
-
1 . JavaScript
50
, - 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;a = b(f());
-
6 .
51
, , , , -. , , - (, [, +, - /. , :
a = b //
var x //
;(f()) //
- var , :
var x //
a = b //
;(f()) //
-, , (.1). - ( - - 13):
// file1.js(function() { // ...})()
// file2.js(function() { // ...})()
-, , . -, :
-
1 . JavaScript
52
(function() { // ...})()(function() { // ...})()
, :
(function() { // ...})()(function() { // ...})();
, , - , , . , , (, [, +, - /:
// file1.js;(function() { // ...})()
// file2.js;(function() { // ...})()
, - :
;(function() { // ...
-
6 .
53
})();(function() { // ...})()
, , - . , , .
: - . , . : , JavaScript -, , - . - JavaScript, - . return, - return - . :
return { };
:
return{ };
- :
return;{ };
, - , return, ,
-
1 . JavaScript
54
return , . - :
yy throw;
yy break continue ;
yy ++ --. - :
a++b
++ , , -- , :
a; ++b;
:
for .
, for . :
for (var i = 0, total = 1 // //
i < n i++) { total *= i}
-
55
7 . 16-
. - :
function infiniteLoop() { while (true) } //
, :
function infiniteLoop() { while (true); }
}, .
, .
, (, [, +, - / .
.
- , - return, throw, break continue, ++ -- .
- for .
7 16-
- ,
-
1 . JavaScript
56
, , . . : - 0 1114111, - (code point). , - , ASCII. , , ASCII - -, . -, , , . , - UTF-8, UTF-16 UTF-32.
, - . , 216 . - UCS-2, 16- , . 16- , - , (code units). UCS-2 16- , . - , , : n- n-16- . .1.1 - , 16- . , - .
-
57
7 . 16-
0x0068
0 1 2 3 4
'h' 'e' 'l' 'l' 'o'
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- , 216 . , ,
-
1 . JavaScript
58
U+1D11E, 119070 UTF-16 0xd834 0xdd1e. , - . ( -, BMP, , , - .) .1.2. , .
0xd834
0 1 2 3 4 5 6
' ' ' 'c' 'l' 'e' 'f'
0xdd1e 0x0020 0x0063 0x006c 0x0065 0x0066
'
. 1.2. JavaScript-,
UTF-16 , 16- - , UTF-16 : n . , n- : , , .
, JavaScript 16- . , length, charAt charCodeAt, , .
-
59
7 . 16-
- , JavaScript , - , UTF-16. :
JavaScript- 16- .
JavaScript- - . , , UTF-16. .1.2. , , JavaScript , 7:
" clef".length; // 7"G clef".length; // 6
, :
" clef".charCodeAt(0); // 55348 (0xd834)" clef".charCodeAt(1); // 56606 (0xdd1e)" clef".charAt(1) === " "; // false" clef".charAt(2) === " "; // true
. (".") :
/^.$/.test(""); // false/^..$/.test(""); // true
, , - , : , length, -
-
1 . JavaScript
. BMP, - , . - , , .
JavaScript - , API- - . , ECMAScript- ; , , URI-: encodeURI, decodeURI, encodeURIComponent decode-URIComponent. JavaScript , , - - - , , , - .
JavaScript- 16- , .
216 JavaScript , .
, length, charAt, charCodeAt , . .
, , .
, , , , .
-
61
2.
. . . ..., .
, -, JavaScript, , . . JavaScript , , , .
8
JavaScript . , . - .
-
2 .
62
, - . , . : - . , -, , , .
- , . - , . . , -, -. , , , :
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;}
averageScore -, score, , - :
-
8 .
63
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"
-
2 .
64
, - - :
var foo = "global foo";this.foo = "changed";foo; // "changed"
, - : -, var, -, - . , var , , . , , - , .
, , - . -, , . , ES5 JSON, JSON. , - JSON, :
if (!this.JSON) {
this.JSON = { parse: ...,
stringify: ...
};}
-
9 .
65
JSON, , , . , - , : -, .
-, - . - , . , , - , JavaScript-.
. . . -
.
9
, , . , JavaScript .
-
2 .
66
, - , . , , - :
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;}
- , - . - - -, , . . -- ( , , ), , - , - . , JavaScript, .
-
10 . with
67
- , , .
var .
-, - .
10 with
with. , JavaScript . with - : -.
with . - , :
function status(info) { var widget = new Widget(); with (widget) { setBackground("blue"); setForeground("white"); setText("Status: " + info); // //
show(); }}
-
2 .
68
with - , :
function f(x, y) { with (Math) { return min(round(x), sqrt(y)); //
}}
with - .
. - , . , : -, , , , - with ( setBackground, round sqrt), -, , , , ( info, x y). .
, JavaScript -: , , . with , with - . , .
.2.1 - JavaScript- status, - with. ES5 (lexical environment), (scope chain).
-
10 . with
69
widget. - info widget. status. , , - , - , . with , .
._background
widget
._foreground
. . .
.info
.widget
.status
.setBackground
Widget.prototype
.setForeground
.setText
.show
. . .
.hasOwnProperty
Object.prototype
.toString
.valueOf
. . .
. 2.1. ( ) status
, , , with,
-
2 .
70
? - with -, with . , with , -. , , , .
with . , widget - info, status - info, . - , , , , info.
, info - - Widget, status :
status("connecting"); // Status: connecting
Widget.prototype.info = "[[widget info]]";status("connected"); // Status: [[widget info]]
f, - Math x y:
Math.x = 0;Math.y = 0;f(2, 9); // 0
, , - - Math x y, , . , -
-
10 . with
71
, , . 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));}
-
2 .
72
, 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");}makeSandwich(); // "peanut butter and jelly"
-
11 .
73
, make magicIngredient, makeSandwich.
, , , ! - , , JavaScript (.19). , :
function sandwichMaker() { var magicIngredient = "peanut butter"; function make(filling) { return magicIngredient + " and " + filling; } return make;}var f = sandwichMaker();f("jelly"); // "peanut butter and jelly"f("bananas"); // "peanut butter and bananas"f("marshmallows"); // "peanut butter and marshmallows"
, make("jelly") - , sandwichMaker make. f make, f make. , , sandwichMaker , make magicIngredient.
? , JavaScript- - , . , . , -, (closures). make ,
-
2 .
74
: magicIngredient filling. make , .
, . sandwichMaker:
function sandwichMaker(magicIngredient) { function make(filling) { return magicIngredient + " and " + filling; } return make;}var hamAnd = sandwichMaker("ham");hamAnd("cheese"); // "ham and cheese"hamAnd("mustard"); // "ham and mustard"var turkeyAnd = sandwichMaker("turkey");turkeyAnd("Swiss"); // "turkey and Swiss"turkeyAnd("Provolone"); // "turkey and Provolone"
, hamAnd turkeyAnd. make, - : magicIngredient "ham", "turkey".
- JavaScript, . JavaScript -:
function sandwichMaker(magicIngredient) { return function(filling) { return magicIngredient + " and " + filling; };}
-
11 .
75
, - : -, , . - (. 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.6b.type(); // "number"
, set (), get () type ( ). - val. set val, get type -.
-
2 .
76
, - .
. ,
, .
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;}
for - player.
-
12 .
77
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(); }
-
2 .
78
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 , , . , , , -.
, JavaScript , , , . trycatch
-
79
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++) {
-
2 .
80
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. .
, .
, , wrapElements, i, . i , , ,
-
81
13 . -
, 5 undefined.
, wrapElements , var for:
function wrapElements(a) { var result = []; for (var i = 0, n = a.length; i < n; i++) { result[i] = function() { return a[i]; }; } return result;}var wrapped = wrapElements([10, 20, 30, 40, 50]);var f = wrapped[0];f(); // undefined
, - var . , . , i .
- :
function wrapElements(a) { var result = []; for (var i = 0, n = a.length; i < n; i++) { (function() { var j = i; result[i] = function() { return a[j]; }; })(); } return result;}
, - (Immediately Invoked Function Expression, IIFE), ,
-
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 .
-
83
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; }
-
2 .
84
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; } return find(tree.left, key) ||
-
85
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,
-
2 .
86
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 , !
-
14 .
, -, null:
var f = function g() { return 17; };var g = null;
var g , - -, - null , .
, , - - - . - , - -. : , - (.1). , , , .
- Error .
- - Object.prototype ES3 JavaScript- .
- - JavaScript- .
- .
, ES5, .
-
2 .
88
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;}
-
89
15 .
test(true); // ?test(false); // ?
, , test ["local", "global"], ["global"], f if. , JavaScript , - f test. , ["local", "local"] ["local"]. JavaScript- . ! - , f , , . ( , -, with.)
ECMAScript? , . ES5 - ; -, . ES5 , JavaScript-, , , , . , .
- -
-
2 .
90
. -, , . , 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 .
-
16 . eval
91
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"
-
2 .
92
, , . , , , . , - , 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"
-
17 . eval
93
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"
-
2 .
94
- , -. , . , 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.
eval - .
-
17 . eval
95
, , , - . 16 , eval, , . , eval . , , eval - , , .
eval . , - , eval.
eval, eval .
eval, .
-
96
3.
JavaScript, - , . , : , , . JavaScript. , - .
18 ,
- -, , , , . JavaScript - .
-
18 . ,
97
:
function hello(username) { return "hello, " + username;}hello("Keyser Sze"); // "hello, Keyser Sze"
, : - hello username .
JavaScript , , :
var obj = { hello: function() {
return "hello, " + this.username; }, username: "Hans Gruber"
};obj.hello(); // "hello, Hans Gruber"
, hello - obj this. , this obj, hello obj. :
var obj2 = { hello: obj.hello,
username: "Boo Radley"
};obj2.hello(); // "hello, Boo Radley"
this, , , . obj.hello() hello obj obj. obj2.hello() hello - obj2 ( , obj.hello), obj2.
-
3 .
98
, , - .
, , , 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, , , . , -
-
18 . ,
99
-, 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 . - - .
-
3 .
100
, .
( undefined , ) . - .
new .
19
- -; , , - . . . , .
, -, -. ( , ) -, , JavaScript.
sort -. ,
-
19 .
101
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]
- . , . . , :
-
3 .
102
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); // 97var 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;}digits; // "0123456789"
-
19 .
103
- - :
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"
-
3 .
var random = buildString(8, function() { return String.fromCharCode(Math.floor(Math.random() * 26) + aIndex);});random; // "ltvisfjr" ( // )
. -, , , , - . , , . - , , - . , , buildString, , , , , .
, , , - . - .
, .
. ,
.
-
20 . call
105
20 call
( , this) - . , this - . , , - -. , :
obj.temporary = f; // obj.temporary // ?
var result = obj.temporary(arg1, arg2, arg3);delete obj.temporary; // obj.temporary // ?
. - obj. , temporary, obj. , , - - . , , - , (.42).
, call. call:
f.call(obj, arg1, arg2, arg3);
, :
f(arg1, arg2, arg3);
-
3 .
106
, call - -.
call , , . 45 - , hasOwnProperty , . - hasOwnProperty -, :
dict.hasOwnProperty = 1;dict.hasOwnProperty("foo"); // : 1 //
call hasOwn-Property , - :
var hasOwnProperty = {}.hasOwnProperty;dict.foo = 1;delete dict.hasOwnProperty;hasOwnProperty.call(dict, "foo"); // truehasOwnProperty.call(dict, "hasOwnProperty"); // false
call . - . , , -, forEach:
var table = { entries: [],
addEntry: function(key, value) {
this.entries.push({ key: key, value: value });
}, forEach: function(f, thisArg) {
var entries = this.entries; for (var i = 0, n = entries.length; i < n; i++) {
-
21 . apply
107
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
, - , - :
-
3 .
108
average(1, 2, 3); // 2average(1); // 1average(3, 1, 4, 1, 5, 9, 2, 6, 5); // 4average(2, 7, 1, 8, 2, 8, 1, 8); // 4.625
average , - ( ): . , average , , , :
averageOfArray([1, 2, 3]); // 2averageOfArray([1]); // 1averageOfArray([3, 1, 4, 1, 5, 9, 2, 6, 5]); // 4averageOfArray([2, 7, 1, 8, 2, 8, 1, 8]); // 4.625
, , . - , , , , , . , :
var scores = getAllScores();
average ?
average(/* ? */);
, - apply, call, . apply , .
, apply , this . average this, null:
-
21 . apply
109
var scores = getAllScores();average.apply(null, scores);
scores , , , :
average(scores[0], scores[1], scores[2]);
apply - . , buffer - append, ( append, - 22):
var buffer = { state: [],
append: function() {
for (var i = 0, n = arguments.length; i < n; i++) { this.state.push(arguments[i]); } }};
-:
buffer.append("Hello, ");buffer.append(firstName, " ", lastName, "!");
buffer.append(newline);
apply this, append :
buffer.append.apply(buffer, getInputStrings());
buffer: , append state .
-
3 .
110
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. avera-geOfArray, ( , - ) .
, - .
-
22 . arguments
111
, 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, -.
-
3 .
112
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);}
-
23 . arguments
113
- :
var obj = { add: function(x, y) { return x + y; }
};callMethod(obj, "add", 17, 25);// : "apply",
// (undefined)
, arguments - . , - arguments. obj argu-ments[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";
-
3 .
114
return x === arguments[0];}function nonstrict(x) { arguments[0] = "modified"; return x === arguments[0];}strict("unmodified"); // falsenonstrict("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; }
};callMethod(obj, "add", 17, 25); // 42
-
24 . arguments
115
arguments .
arguments , [].slice.call(arguments) .
24 arguMEntS
, - . API- next, . , , , :
var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);it.next(); // 1it.next(); // 4it.next(); // 1
values -, , - arguments:
function values() { var i = 0, n = arguments.length; return { hasNext: function() {
return i < n; }, next: function() {
-
3 .
116
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)
, argu-ments . 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(" ");
}
-
25 . bind
117
return a[i++]; } };}var it = values(1, 4, 1, 4, 2, 1, 3, 5, 6);it.next(); // 1it.next(); // 4it.next(); // 1
arguments - .
arguments , arguments, .
25 bind
, , - . , , . , , :
var buffer = { entries: [],
-
3 .
118
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"
- , . forEach - , ? , buffer.add:
-
25 . bind
119
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 , - . , --
-
3 .
120
: - . ( 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);});
-
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 .
122
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(); end.push(Date.now())");
-
27 . ,
123
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 , :
-
3 .
124
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 toString
JavaScript - :
-
28 . toString
125
(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 (, - ) , .
-
3 .
126
, , to-String, , -, -. :
(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 .
-
29 .
127
29
JavaScript- : - ( . 64). arguments : arguments.callee , arguments, - arguments.caller , . - , , :
var factorial = (function(n) { return (n
-
3 .
128
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); //
-
29 .
129
? f , caller , f. getCallStack , f. , , f , .
. , ES5; caller callee - arguments :
function f() { "use strict"; return f.caller;}f(); // : caller
//
. - , - .
arguments.caller ar-guments.callee, .
caller , - .
-
130
4.
JavaScript -. - . , .
- , JavaScript : - . , JavaScript , . JavaScript - , .
- , , . JavaScript . . - , . - , - .
-
131
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");
-
4 .
132
User prototype, , - - . User.prototype : toString checkPassword. User new, - u , - User.prototype, -. .4.1.
. 4.1. User
-
133
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 ,
-
4 .
. - User u - .
. 4.2. User
C.prototype - new C() .
Object.getPrototypeOf(obj) , - ES5 .
obj.__proto__ - .
, -- .
-
135
31 . Object .getPrototypeOf
31 obJEct.gEtprototypEof, __proto__
API- -- ES5 Object.getPrototypeOf, , JavaScript- - __proto__. JavaScript-, , , . , , null. __proto__ Object.proto-type, , null __proto__:
var empty = Object.create(null); // ,
"__proto__" in empty; // false ( )
__proto__ :
var empty = Object.create(null); // ,
"__proto__" in empty; // true ( )
Object.getPrototypeOf, . , __proto__ - , (.45). , JavaScript-, , - __proto__. -
-
4 .
136
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 __proto__
__proto__ - ,
-
32 . __proto__
137
Object.getPrototypeOf, - -. ( , , ?), - . : , - , __proto__.
, - __proto__, . JavaScript- , , - JavaScript-. , -. , , , -, . __proto__ , , , , , .
, - __proto__, - . , . - - . - , , - , .
-
4 .
138
- 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", "d8b74df393528d51cd19980ae0aa028e");
-
139
33 . , new
u; // undefinedthis.name; // "baravelli"this.passwordHash; // "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)) {
-
4 .
140
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; // truey 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;}
Object.create - - , . , User , , - User.prototype name passwordHash.
-
141
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 , .
-
4 .
142
, ; 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(/* ... */);
.4.3 , -. -
-
34 .
143
toString checkPassword , , .
. 4.3. -
.4.4 , - -. toString checkPassword . , . , , , u3.toString(), toString - ? JavaScript- , - -
-
4 .
144
. - , .
. 4.4. -
- , - .
, - .
35
JavaScript - ,
-
35 .
145
. , - , . , for...in ES5 Object.keys() Object.getOwnPropertyNames(), - .
JavaScript- - , - . , - , - (_). , , , , .
. , - - , . , , - , - .
JavaScript - .
. , - . . , :
-
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 . -
147
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);
-
4 .
148
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); }};
-
36 . -
149
, , .4.6.
. 4.6. -
, , , - . , , , , this. ( , this - , , .) , - . , , , - . , --, . , , -.
-
4 .
150
- , .
, -, - .
37 thiS
CSV (Comma-Separated Values -, ) :
Bsendorfer,1828,Vienna,Austria
Fazioli,1981,Sacile,ItalySteinway,1853,New York,USA
CSV- - . ( , , , "hello, world".) , CSV , . - - , :
function CSVReader(separators) {
this.separators = separators || [","]; this.regexp = new RegExp(this.separators.map(function(sep) { return "\\" + sep[0]; }).join("|"));}
-
37 . this
151
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.
-
4 .
152
, forEach, - 25, -, map, , , this . , this map:
CSVReader.prototype.read = function(str) {
var lines = str.trim().split(/\n/); return lines.map(function(line) { return line.split(this.regexp); }, this); // this //
};
var reader = new CSVReader();
reader.read("a,b,c\nd,e,f\n");// [["a","b","c"], ["d","e","f"]]
API-, . , map ? - this , - this. : this :
CSVReader.prototype.read = function(str) {
var lines = str.trim().split(/\n/); var self = this; // // this
return lines.map(function(line) { return line.split(self.regexp); // 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 .
154
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(); }};
-
38 .
155
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 - drawImage):
Actor.prototype.draw = function() { var image = this.scene.images[this.type];
-
4 .
156
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);
( 33 Object.create , ES5.)
-
38 .
157
- 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);};
-
4 .
158
.4.7 SpaceShip. , scene, x y -, -, - Actor.
. 4.7.
-
39 .
159
-, 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);
-
4 .
160
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, strength) {
-
40 .
161
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;
-
4 .
162
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.
, [[Class]] length? , length , [[Class]] Array. length . - , length - , length, , , .
-
40 .
163
4.1. [[Class]], ECMAScript
[[claSS]]
"Array" new Array(...), [...]
"Boolean" new Boolean(...)
"Date" new Date(...)
"Error" new Error(...), new EvalError(...), new RangeError(...), new ReferenceError(...), new SyntaxError(...), new TypeError(...), new URIError(...)
"Function" new Function(...), function(...) {...}
"JSON" JSON
"Math" Math
"Number" new Number(...)
"Object" new Object(...), {...}, new MyClass(...)
"RegExp" new RegExp (...), /.../
"String" new String (...)
Array, - new Array() []. Dir [[Class]] "Object". : Object.prototype.toString [[Class]] , :
var dir = new Dir("/", []);Object.prototype.toString.call(dir); // "[object Object]"Object.prototype.toString.call([]); // "[objectArray]"
Dir - length, .
- :
-
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 .
165
. , . , - , , . : .
JavaScript - (introspection) . Object.prototype.hasOwnProperty -, ( ), -. Object.getPrototypeOf __proto__ (.30) -. .
, . , , . , -, , . , : - , ( ) .
, JavaScript (.35). -. , - , .
-
4 .
166
, . ,
.
, , .
42
41 . - , , , . (monkey-patching).
. ? :
Array.prototype.split = function(i) { // 1
return [this.slice(0, i), this.slice(i)];};
: split.
- , . ,