summaryrefslogtreecommitdiffhomepage
path: root/uk-ua/javascript-ua.html.markdown
blob: a84eba676699bb135c08708a4ec28f8e8ece0aa5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
---
language: javascript
contributors:
    - ["Adam Brenecki", "http://adam.brenecki.id.au"]
    - ["Ariel Krakowski", "http://www.learneroo.com"]
    - ["clearsense", "https://github.com/clearsense"]
filename: javascript-uk.js
translators:
  - ["Ivan", "https://github.com/IvanEh"]
  - ["Serhii Maksymchuk", "https://github.com/Serg-Maximchuk"]
lang: uk-ua
---

JavaScript було створено в 1995 році Бренданом Айком, який працював у копаніх Netscape.
Він був задуманий як проста мова сценаріїв для веб-сайтів, який би доповнював Java
для більш складних веб-застосунків. Але тісна інтеграція з веб-сторінками і
вбудована підтримка браузерами призвела до того, що JavaScript став популярніший
за власне Java.

Зараз JavaScript не обмежується тільки веб-браузеорм. Наприклад, Node.js,
програмна платформа, що дозволяє виконувати JavaScript код з використанням
рушія V8 від браузера Google Chrome, стає все більш і більш популярною.

```js
// С-подібні коментарі. Однорядкові коментарі починаються з двох символів /(слеш)
/* а багаторядкові коментарі починаються з послідовності слеша та зірочки і
   закінчуються символами зірочка-слеш */

//Інструкції можуть закінчуватися крапкою з комою ;
doStuff();

// ... але не обов’язково, тому що крапка з комою автоматично вставляється на
// місці символу нового рядка, крім деяких випадків.
doStuff()

// Ми завжди будемо використовувати крапку з комою в цьому посібнику, тому що ці
// винятки можуть призвести до неочікуваних результатів

///////////////////////////////////
// 1. Числа, Рядки і Оператори

// В JavaScript числа зберігаються тільки в одному форматі (64-bit IEEE 754 double)
// Цей тип має 52-бітну мантису, якої достатньо для збереження чисел з
// точністю до 9✕10¹⁵.
3; // = 3
1.5; // = 1.5

// Деякі прості арифметичні операції працють так, як ми очікуємо.
1 + 1; // = 2
0.1 + 0.2; // = 0.30000000000000004 (а деякі - ні)
8 - 1; // = 7
10 * 2; // = 20
35 / 5; // = 7

// В тому числі ділення з остачею
5 / 2; // = 2.5

// В JavaScript є побітові операції; коли ви виконуєте таку операцію,
// число з плаваючою точкою переводиться в ціле зі знаком
// довжиною *до* 32 розрядів.
1 << 2; // = 4

// Пріоритет у виразах можна задати явно круглими дужками
(1 + 3) * 2; // = 8

// Є три спеціальні значення, які не є реальними числами:
Infinity; // "нескінченність", наприклад, як результат ділення на 0
-Infinity; // "мінус нескінченність", як результат ділення від’ємного числа на 0
NaN; // "не число", наприклад, ділення 0/0

// Логічні типи
true;
false;

// Рядки створюються за допомогою подвійних та одинарних лапок
'абв';
"Привіт, світе!";

// Для логічного заперечення використовується знак оклику.
!true; // = false
!false; // = true

// Строга рівність ===
1 === 1; // = true
2 === 1; // = false

// Строга нерівність !==
1 !== 1; // = false
2 !== 1; // = true

// Інші оператори порівняння
1 < 10; // = true
1 > 10; // = false
2 <= 2; // = true
2 >= 2; // = true

// Рядки об’єднуються за допомогою оператора +
"hello, " + "world!"; // = "hello, world!"

// І порівнюються за допомогою > та <
"a" < "b"; // = true

// Перевірка на рівність з приведнням типів здійснюється оператором ==
"5" == 5; // = true
null == undefined; // = true

// ... але приведення не виконується при ===
"5" === 5; // = false
null === undefined; // = false 

// ... приведення типів може призвести до дивних результатів
13 + !0; // 14
"13" + !0; // '13true'

// Можна отримати доступ до будь-якого символа рядка за допомгою charAt
"Це рядок".charAt(0);  // = 'Ц'

// ... або використати метод substring, щоб отримати більший кусок
"Hello, world".substring(0, 5); // = "Hello"

// length - це не метод, а поле
"Hello".length; // = 5

// Типи null и undefined
null; // навмисна відсутність результату
undefined; // використовується для позначення відсутності присвоєного значення

// false, null, undefined, NaN, 0 та "" — хиба; все інше - істина.
// Потрібно відмітити, що 0 — це хиба, а "0" — істина, не зважаючи на те що:
// 0 == "0".

///////////////////////////////////
// 2. Змінні, Масиви, Об’єкти

// Змінні оголошуються за допомогою ключового слова var. JavaScript — мова з
// динамічною типізацією, тому не потрібно явно вказувати тип. Для присвоєння
// значення змінної використовується символ =
var someVar = 5;

// якщо пропустити слово var, ви не отримаєте повідомлення про помилку, ...
someOtherVar = 10;

// ... але вашу змінну буде створено в глобальному контексті, а не там, де
// ви її оголосили

// Змінні, які оголошені без присвоєння, автоматично приймають значення undefined
var someThirdVar; // = undefined

// У математичних операцій є скорочені форми:
someVar += 5; // як someVar = someVar + 5;
someVar *= 10; // тепер someVar = 100

// Інкремент і декремент
someVar++; // тепер someVar дорівнює 101
someVar--; // а зараз 100

// Масиви — це нумеровані списки, які зберігають значення будь-якого типу.
var myArray = ["Привіт", 45, true];

// Доступ до елементів можна отримати за допомогою синтаксиса з квадратними дужками
// Індексація починається з нуля
myArray[1]; // = 45

// Масиви в JavaScript змінюють свою довжину при додаванні нових елементів
myArray.push("Привіт");
myArray.length; // = 4

// Додавання і редагування елементів
myArray[3] = "світ";

// Об’єкти в JavaScript схожі на словники або асоціативні масиви в інших мовах
var myObj = {key1: "Hello", key2: "World"};

// Ключі - це рядки, але лапки не обов’язкі, якщо ключ задовольняє
// правилам формування назв змінних. Значення можуть бути будь-яких типів.
var myObj = {myKey: "myValue", "my other key": 4};

// Атрибути можна отримати використовуючи квадратні дужки
myObj["my other key"]; // = 4

// Або через точку, якщо ключ є правильним ідентифікатором
myObj.myKey; // = "myValue"

// Об’єкти можна динамічно змінювати й додавати нові поля
myObj.myThirdKey = true;

// Коли ви звертаєтесь до поля, що не існує, ви отримуєте значення undefined
myObj.myFourthKey; // = undefined

///////////////////////////////////
// 3. Керуючі конструкції

// Синтаксис для цього розділу майже такий самий, як у Java

// Умовна конструкція
var count = 1;
if (count == 3) {
    // виконується, якщо count дорівнює 3
} else if (count == 4) {
    // ..
} else {
    // ...
}

// ...  цикл while.
while (true){
    // Нескінченний цикл!
}

// Цикл do-while такий самий, як while, але завжди виконується принаймні один раз.
var input
do {
    input = getInput();
} while (!isValid(input))

// цикл for такий самий, як в C і Java:
// ініціалізація; умова; крок.
for (var i = 0; i < 5; i++) {
    // виконається 5 разів
}

// && — логічне І, || — логічне АБО
if (house.size == "big" && house.color == "blue") {
    house.contains = "bear";
}
if (color == "red" || color == "blue") {
    // колір червоний або синій
}

// && та || використовують скорочене обчислення
// тому їх можна використовувати для задання значень за замовчуванням.
var name = otherName || "default";

// Оператор switch виконує перевірку на рівність за допомогою ===
// використовуйте break, щоб призупити виконання наступного case,  
grade = 4;
switch (grade) {
  case 5:
    console.log("Відмінно");
    break;
  case 4:
    console.log("Добре");
    break;
  case 3:
    console.log("Можна краще");
    break;
  default:
    console.log("Погано!");
    break;
}


///////////////////////////////////
// 4. Функції, область видимості і замикання

// Функції в  JavaScript оголошуються за допомогою ключового слова function.
function myFunction(thing) {
    return thing.toUpperCase();
}
myFunction("foo"); // = "FOO"
 
// Зверніть увагу, що значення яке буде повернено, повинно починатися на тому ж
// рядку, що і ключове слово return, інакше завжди буде повертатися значення undefined
// через автоматичну вставку крапки з комою
function myFunction()
{
    return // <- крапка з комою вставляється автоматично
    {
        thisIsAn: 'object literal'
    }
}
myFunction(); // = undefined

// В JavaScript функції - це об`єкти першого класу, тому вони можуть присвоюватися
// іншим змінним і передаватися іншим функціям, наприклад, щоб визначити обробник
// події.
function myFunction() {
    // код буде виконано через 5 сек.
}
setTimeout(myFunction, 5000);
// setTimeout не є частиною мови, але реалізований в браузерах і Node.js

// Функції не обов’язково мають мати ім’я при оголошенні — ви можете написати
// анонімну функцію як аргумент іншої функції
setTimeout(function() {
    // Цей код буде виконано через п’ять секунд
}, 5000);

// В JavaScript реалізована концепція області видимості; функції мають свою
// область видимості, а інші блоки не мають
if (true) {
    var i = 5;
}
i; // = 5, а не undefined, як це звичайно буває в інших мовах

// Така особливість призвела до шаблону "анонімних функцій, які викликають самих себе"
// що дозволяє уникнути проникнення змінних в глобальну область видимості
(function() {
    var temporary = 5;
    // об’єкт window зберігає глобальний контекст; таким чином ми можемо також додавати
    // змінні до глобальної області
    window.permanent = 10;
})();
temporary; // повідомлення про помилку ReferenceError
permanent; // = 10

// Замикання - один з найпотужніших інструментів JavaScript. Якщо функція визначена
// всередині іншої функції, то внутрішня функція має доступ до змінних зовнішньої
// функції навіть після того, як код буде виконуватися поза контекстом зовнішньої функції
function sayHelloInFiveSeconds(name) {
    var prompt = "Привіт, " + name + "!";
    // Внутрішня функція зберігається в локальній області так,
    // ніби функція була оголошена за допомогою ключового слова var
    function inner() {
        alert(prompt);
    }
    setTimeout(inner, 5000);
    // setTimeout асинхронна, тому функція sayHelloInFiveSeconds одразу завершиться,
    // після чого setTimeout викличе функцію inner. Але функція inner
    // «замкнута» кругом sayHelloInFiveSeconds, вона все рівно має доступ до змінної prompt
}
sayHelloInFiveSeconds("Адам"); // Через 5 с відкриється вікно «Привіт, Адам!»

///////////////////////////////////
// 5. Об’єкти: конструктори і прототипи

// Об’єкти можуть містити функції
var myObj = {
    myFunc: function() {
        return "Hello, world!";
    }
};
myObj.myFunc(); // = "Hello, world!"

// Функції, що прикріплені до об’єктів мають доступ до поточного об’єкта за 
// допомогою ключового слова this.
myObj = {
    myString: "Hello, world!",
    myFunc: function() {
        return this.myString;
    }
};
myObj.myFunc(); // = "Hello, world!"

// Значення this залежить від того, як функція викликається
// а не від того, де вона визначена. Таким чином наша функція не працює, якщо
// вона викликана не в контексті об’єкта
var myFunc = myObj.myFunc;
myFunc(); // = undefined

// Функція може бути присвоєна іншому об’єкту. Тоді вона матиме доступ до 
// цього об’єкта через this
var myOtherFunc = function() {
    return this.myString.toUpperCase();
}
myObj.myOtherFunc = myOtherFunc;
myObj.myOtherFunc(); // = "HELLO, WORLD!"

// Контекст виконання функції можна задати за допомогою сall або apply
var anotherFunc = function(s) {
    return this.myString + s;
}
anotherFunc.call(myObj, " Hello!"); // = "Hello, world! Hello!"

// Функцiя apply приймає в якості аргументу масив
anotherFunc.apply(myObj, [" Hello!"]); // = "Hello, world! Hello!"

// apply можна використати, коли функція працює послідовністю аргументів, а
// ви хочете передати масив
Math.min(42, 6, 27); // = 6
Math.min([42, 6, 27]); // = NaN (Ой-ой!)
Math.min.apply(Math, [42, 6, 27]); // = 6

// Але call і apply — тимчасові. Коли ми хочемо зв’язати функцію і об’єкт 
// використовують bind
var boundFunc = anotherFunc.bind(myObj);
boundFunc(" Hello!"); // = "Hello world, Hello!"

// Bind можна використати для задання аргументів
var product = function(a, b) { return a * b; }
var doubler = product.bind(this, 2);
doubler(8); // = 16

// Коли ви викликаєте функцію за допомогою ключового слова new, створюється новий об’єкт,
// доступний функції за допомогою this. Такі функції називають конструкторами.
var MyConstructor = function() {
    this.myNumber = 5;
}
myNewObj = new MyConstructor(); // = {myNumber: 5}
myNewObj.myNumber; // = 5

// У кожного об’єкта є прототип. Коли ви звертаєтесь до поля, яке не існує в цьому
// об’єкті, інтерпретатор буде шукати поле в прототипі

// Деякі реалізації мови дозволяють отримати доступ до прототипа об’єкта через
// "магічну" властивість __proto__. Це поле не є частиною стандарта, але існують
// стандартні способи використання прототипів, які ми побачимо пізніше
var myObj = {
    myString: "Hello, world!"
};
var myPrototype = {
    meaningOfLife: 42,
    myFunc: function() {
        return this.myString.toLowerCase()
    }
};

myObj.__proto__ = myPrototype;
myObj.meaningOfLife; // = 42

// Аналогічно для функцій
myObj.myFunc(); // = "hello, world!"

// Якщо інтерпретатор не знайде властивості в прототипі, то він продовжить пошук
// в прототипі прототипа і так далі
myPrototype.__proto__ = {
    myBoolean: true
};
myObj.myBoolean; // = true

// Кожен об’єкт зберігає посилання на свій прототип. Це значить, що ми можемо змінити
// наш прототип, і наші зміни будуть всюди відображені.
myPrototype.meaningOfLife = 43;
myObj.meaningOfLife; // = 43

// Ми сказали, що властивість __proto__ нестандартна, і нема ніякого стандартного способу
// змінити прототип об’єкта, що вже існує. Але є два способи створити новий об’єкт із заданим
// прототипом

// Перший спосіб — це Object.create, який з’явився в JavaScript недавно,
// а тому в деяких реалізаціях може бути недоступним.
var myObj = Object.create(myPrototype);
myObj.meaningOfLife; // = 43

// Другий спосіб: у конструкторів є властивість з іменем prototype. Це *не*
// прототип функції-конструктора, це прототип для нових об’єктів, які будуть створені
// цим конструктором і ключовим словом new.
MyConstructor.prototype = {
    myNumber: 5,
    getMyNumber: function() {
        return this.myNumber;
    }
};
var myNewObj2 = new MyConstructor();
myNewObj2.getMyNumber(); // = 5
myNewObj2.myNumber = 6
myNewObj2.getMyNumber(); // = 6

// У вбудованих типів(рядок, число) теж є конструктори, які створють еквівалентні
// об’єкти-обгортки
var myNumber = 12;
var myNumberObj = new Number(12);
myNumber == myNumberObj; // = true

// Але вони не ідентичні
typeof myNumber; // = 'number'
typeof myNumberObj; // = 'object'
myNumber === myNumberObj; // = false

// Об’єкти-обгортки і вбудовані типи мають спільні прототипи, тому
// ви можете розширити функціонал рядків:
String.prototype.firstCharacter = function() {
    return this.charAt(0);
}
"abc".firstCharacter(); // = "a"

// Такий прийом часто використовуються в поліфілах, які реалізують нові можливості
// JavaScript в старій реалізації мови, так що вони можуть бути використані в старих
// середовищах

// Наприклад, Object.create доступний не у всіх реалізаціях, але ми можемо
// використати функції за допомогою наступного поліфіла:
if (Object.create === undefined) { // не перезаписуємо метод, якщо він існує
    Object.create = function(proto) {
        // Створюємо правильний конструктор з правильним прототипом
        var Constructor = function(){};
        Constructor.prototype = proto;
    
        return new Constructor();
    }
}
```

## Що почитати

* [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript
* [2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
* [3]: https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core
* [4]: http://www.learneroo.com/modules/64/nodes/350
* [5]: http://bonsaiden.github.io/JavaScript-Garden/
* [6]: http://www.amazon.com/gp/product/0596805527/
* [7]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
* [8]: http://eloquentjavascript.net/
* [9]: http://jstherightway.org/