renovations
This commit is contained in:
parent
c7d4c7e3ff
commit
e1948130f6
170 changed files with 1496 additions and 1161 deletions
|
@ -37,7 +37,9 @@ log(a,b,c); // вызовется вторая функция
|
|||
|
||||
Это называется "полиморфизмом функций" или "перегрузкой функций". В JavaScript ничего подобного нет.
|
||||
|
||||
**Может быть только одна функция с именем `log`, которая вызывается с любыми аргументами.** А уже внутри она может посмотреть, с чем вызвана и по-разному отработать.
|
||||
**Может быть только одна функция с именем `log`, которая вызывается с любыми аргументами.**
|
||||
|
||||
А уже внутри она может посмотреть, с чем вызвана и по-разному отработать.
|
||||
|
||||
В примере выше второе объявление `log` просто переопределит первое.
|
||||
[/smart]
|
||||
|
@ -142,9 +144,7 @@ for(var i=0; i<arguments.length; i++) {
|
|||
|
||||
Такие объекты иногда называют *"коллекциями"* или *"псевдомассивами"*.
|
||||
|
||||
## Примеры работы с аргументами
|
||||
|
||||
### Копирование объектов copy(dst, src1, src2...) [#copy]
|
||||
## Пример: копирование свойств copy(dst, src1, src2...) [#copy]
|
||||
|
||||
Иногда встаёт задача -- скопировать в существующий объект свойства из одного или нескольких других.
|
||||
|
||||
|
@ -206,12 +206,14 @@ var userClone = copy({}, user);
|
|||
//+ autorun
|
||||
function copy() {
|
||||
var dst = arguments[0];
|
||||
|
||||
for (var i=1; i<arguments.length; i++) {
|
||||
var arg = arguments[i];
|
||||
for (var key in arg) {
|
||||
dst[key] = arg[key];
|
||||
}
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
```
|
||||
|
@ -229,6 +231,7 @@ function copy(dst) {
|
|||
dst[key] = arg[key];
|
||||
}
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
```
|
||||
|
@ -333,14 +336,17 @@ showWarning(opts); // вызвать с новым текстом, без коп
|
|||
|
||||
## Устаревшее свойство arguments.callee [#arguments-callee]
|
||||
|
||||
В старом стандарте JavaScript объект `arguments` не только хранил список аргументов, но и содержал в свойстве `arguments.callee` ссылку на функцию, которая выполняется в данный момент.
|
||||
|
||||
[warn header="Используйте NFE вместо `arguments.callee`"]
|
||||
Это свойство устарело, при `use strict` оно не работает, но ещё встречается в старом коде, поэтому о нём желательно знать.
|
||||
Это свойство устарело, при `use strict` оно не работает.
|
||||
|
||||
Единственная причина, по которой оно тут -- это то, что его можно встретить в старом коде, поэтому о нём желательно знать.
|
||||
|
||||
Современная спецификация рекомендует использовать ["именованные функциональные выражения (NFE)"](#functions-nfe).
|
||||
|
||||
[/warn]
|
||||
|
||||
В старом стандарте JavaScript объект `arguments` не только хранил список аргументов, но и содержал в свойстве `arguments.callee` ссылку на функцию, которая выполняется в данный момент.
|
||||
|
||||
Например:
|
||||
|
||||
```js
|
||||
|
@ -366,7 +372,7 @@ var factorial = function(n) {
|
|||
};
|
||||
```
|
||||
|
||||
В учебнике мы его использовать не будем, оно приведено для общего ознакомления, так как пока ещё много старого кода использует его.
|
||||
В учебнике мы его использовать не будем, оно приведено для общего ознакомления.
|
||||
|
||||
### arguments.callee.caller
|
||||
|
||||
|
@ -375,7 +381,7 @@ var factorial = function(n) {
|
|||
[warn header="Это свойство тоже устарело"]
|
||||
Это свойство было в старом стандарте, при `use strict` оно не работает, как и `arguments.callee`.
|
||||
|
||||
Также ранее существовало похожее свойство `arguments.caller` (без `callee`). Но это уже вообще раритет, оно даже не кросс-браузерное. А вот свойство `arguments.callee.caller` поддерживается везде, если не использован `use strict`, поэтому в старом коде оно встречается.
|
||||
Также ранее существовало более короткое свойство `arguments.caller`. Но это уже раритет, оно даже не кросс-браузерное. А вот свойство `arguments.callee.caller` поддерживается везде, если не использован `use strict`, поэтому в старом коде оно встречается.
|
||||
[/warn]
|
||||
|
||||
Пример работы:
|
||||
|
|
|
@ -29,24 +29,29 @@ alert( Jan02_1970 );
|
|||
|
||||
</dd>
|
||||
<dt>`new Date(datestring)`</dt>
|
||||
<dd>Если единственный аргумент - строка, используется вызов `Date.parse` для ее разбора.</dd>
|
||||
<dd>Если единственный аргумент - строка, используется вызов `Date.parse` (см. далее) для чтения даты из неё.</dd>
|
||||
<dt>`new Date(year, month, date, hours, minutes, seconds, ms)`</dt>
|
||||
<dd>Дату можно создать, используя компоненты в местной временной зоне. Для этого формата обязательны только первые два аргумента. Отсутствующие параметры, начиная с `hours` считаются равными нулю, а `date` -- единице.
|
||||
|
||||
**Заметим, что год `year` должен быть из 4 цифр, а отсчет месяцев `month` начинается с нуля 0.** Например:
|
||||
Заметим:
|
||||
<ul>
|
||||
<li>Год `year` должен быть из 4 цифр.</li>
|
||||
<li>Отсчет месяцев `month` начинается с нуля 0.</li>
|
||||
</ul>
|
||||
|
||||
Например:
|
||||
|
||||
```js
|
||||
new Date(2011, 0, 1) // 1 января 2011, 00:00:00 в местной временной зоне
|
||||
new Date(2011, 0) // то же самое, date по умолчанию равно 1
|
||||
new Date(2011, 0, 1, 0, 0, 0, 0); // то же самое
|
||||
new Date(2011, 0, 1, 0, 0, 0, 0); // // 1 января 2011, 00:00:00
|
||||
new Date(2011, 0, 1); // то же самое, часы/секунды по умолчанию равны 0
|
||||
```
|
||||
|
||||
Дата задана с точностью до миллисекунд:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var d = new Date(2011, 0, 1, 2, 3, 4, 567);
|
||||
alert(d); // 1.01.2011, 02:03:04.567
|
||||
var date = new Date(2011, 0, 1, 2, 3, 4, 567);
|
||||
alert(date); // 1.01.2011, 02:03:04.567
|
||||
```
|
||||
|
||||
</dd>
|
||||
|
@ -67,7 +72,7 @@ alert(d); // 1.01.2011, 02:03:04.567
|
|||
<dd>Получить соответствующие компоненты.</dd>
|
||||
</dl>
|
||||
|
||||
[warn header="Устаревший `getYear()`"]
|
||||
[warn header="Не `getYear()`, а `getFullYear()`"]
|
||||
Некоторые браузеры реализуют нестандартный метод `getYear()`. Где-то он возвращает только две цифры из года, где-то четыре. Так или иначе, этот метод отсутствует в стандарте JavaScript. Не используйте его. Для получения года есть `getFullYear()`.
|
||||
[/warn]
|
||||
|
||||
|
@ -85,17 +90,22 @@ alert(d); // 1.01.2011, 02:03:04.567
|
|||
|
||||
```js
|
||||
//+ run
|
||||
// текущая дата
|
||||
var date = new Date();
|
||||
|
||||
alert( date.getHours() ); // час в вашей зоне для даты date
|
||||
alert( date.getUTCHours() ); // час в зоне GMT+0 для даты date
|
||||
// час в текущей временной зоне
|
||||
alert( date.getHours() );
|
||||
|
||||
// сколько сейчас времени в Лондоне?
|
||||
// час в зоне GMT+0
|
||||
alert( date.getUTCHours() );
|
||||
```
|
||||
|
||||
Кроме описанных выше, существуют два специальных метода без UTC-варианта:
|
||||
|
||||
<dl>
|
||||
<dt>`getTime()`</dt>
|
||||
<dd>Возвращает число миллисекунд, прошедших с 01.01.1970 00:00:00 UTC. Это то же число, которое используется в конструкторе `new Date(milliseconds)`.</dd>
|
||||
<dd>Возвращает число миллисекунд, прошедших с 1 января 1970 года GMT+0, то есть того же вида, который используется в конструкторе `new Date(milliseconds)`.</dd>
|
||||
<dt>`getTimezoneOffset()`</dt>
|
||||
<dd>Возвращает разницу между местным и UTC-временем, в минутах.
|
||||
|
||||
|
@ -296,7 +306,9 @@ alert('Время walkLength: ' +timeLength + 'мс');
|
|||
```
|
||||
|
||||
[smart header="Более точное время с `performance.now()`"]
|
||||
В современных браузерах (кроме IE9-) вызов [performance.now()](https://developer.mozilla.org/en-US/docs/Web/API/performance.now) возвращает количество миллисекунд, прошедшее с начала загрузки страницы, а если точнее -- с момента выгрузки предыдущей страницы из памяти.
|
||||
В современных браузерах (кроме IE9-) вызов [performance.now()](https://developer.mozilla.org/en-US/docs/Web/API/performance.now) возвращает количество миллисекунд, прошедшее с начала загрузки страницы. Причём именно с самого начала, до того, как загрузился HTML-файл, если точнее -- с момента выгрузки предыдущей страницы из памяти.
|
||||
|
||||
Так что это время включает в себя всё, включая начальное обращение к серверу.
|
||||
|
||||
Его можно посмотреть в любом месте страницы, даже в `<head>`, чтобы узнать, сколько времени потребовалось браузеру, чтобы до него добраться, включая загрузку HTML.
|
||||
|
||||
|
@ -348,17 +360,17 @@ console.timeEnd("All Benchmarks");
|
|||
<li>Автоматически выносят инвариант, то есть постоянное в цикле значение типа `arr.length`, за пределы цикла.</li>
|
||||
<li>Стараются понять, значения какого типа хранит данная переменная или массив, какую структуру имеет объект и, исходя из этого, оптимизировать внутренние алгоритмы.</li>
|
||||
<li>Выполняют простейшие операции, например сложение явно заданных чисел и строк, на этапе компиляции.</li>
|
||||
<li>В теории, могут выкинуть код, который ни на что не влияет, например присваивание к неиспользуемой локальной переменной, хотя делают это редко.</li>
|
||||
<li>Могут обнаружить, что некий код, например присваивание к неиспользуемой локальной переменной, ни на что не влияет и вообще исключить его из выполнения, хотя делают это редко.</li>
|
||||
</ol>
|
||||
Они могут влиять на результаты тестов.
|
||||
Эти оптимизации могут влиять на результаты тестов, поэтому измерять скорость базовых операций JavaScript ("проводить миробенчмаркинг") до того, как вы изучите внутренности JavaScript-интерпретаторов и поймёте, что они реально делают на таком коде, не рекомендуется.
|
||||
[/warn]
|
||||
|
||||
|
||||
## Форматирование
|
||||
## Форматирование и вывод дат
|
||||
|
||||
Во всех браузерах, кроме IE10-, поддерживается новый стандарт [Ecma 402](http://www.ecma-international.org/publications/standards/Ecma-402.htm), который добавляет специальные методы для форматирования дат.
|
||||
|
||||
Это делается взыовом `date.toLocaleString(локаль, опции)`, у которого много настроек. Он позволяет указать, какие параметры даты нужно вывести, и ряд настроек вывода, после чего интерпретатор сам сформирует строку.
|
||||
Это делается вызовом `date.toLocaleString(локаль, опции)`, в котором можно задать много настроек. Он позволяет указать, какие параметры даты нужно вывести, и ряд настроек вывода, после чего интерпретатор сам сформирует строку.
|
||||
|
||||
Пример с почти всеми параметрами даты и русским, затем английским (США) форматированием:
|
||||
|
||||
|
@ -389,7 +401,7 @@ alert( date.toLocaleString("en-US", options) ); // Wednesday, December 31, 2014
|
|||
|
||||
<dl>
|
||||
<dt>`toString()`, `toDateString()`, `toTimeString()`</dt>
|
||||
<dd>Возвращают стандартное строчное представление, не указанное в стандарте, а зависящее от браузера. Единственное требование - читаемость человеком. Метод `toString` возвращает дату целиком, `toDateString()` и `toTimeString()` - только дату и время соответственно.
|
||||
<dd>Возвращают стандартное строчное представление, не заданное жёстко в стандарте, а зависящее от браузера. Единственное требование к нему -- читаемость человеком. Метод `toString` возвращает дату целиком, `toDateString()` и `toTimeString()` -- только дату и время соответственно.
|
||||
|
||||
```js
|
||||
//+ run
|
||||
|
@ -413,7 +425,7 @@ alert( d.toISOString() ); // вывод, похожий на '2011-01-26T13:51:5
|
|||
|
||||
</dd></dl>
|
||||
|
||||
**Если хочется иметь большую гибкость и кросс-браузерность, то также можно воспользоваться специальной библиотекой, например [Moment.JS](http://momentjs.com/) или написать свою функцию.**
|
||||
Если хочется иметь большую гибкость и кросс-браузерность, то также можно воспользоваться специальной библиотекой, например [Moment.JS](http://momentjs.com/) или написать свою функцию форматирования.
|
||||
|
||||
|
||||
|
||||
|
@ -421,31 +433,29 @@ alert( d.toISOString() ); // вывод, похожий на '2011-01-26T13:51:5
|
|||
|
||||
Все современные браузеры, включая IE9+, понимают даты в упрощённом формате ISO 8601 Extended.
|
||||
|
||||
Этот формат выглядит так: `YYYY-MM-DDTHH:mm:ss.sssZ`. Для разделения даты и времени в нем используется символ `'T'`. Часть `'Z'` обозначает (необязательную) временную зону -- она может отсутствовать, тогда зона UTC, либо может быть символ `z` -- тоже UTC, или зона в формате `+-hh:mm`.
|
||||
Этот формат выглядит так: `YYYY-MM-DDTHH:mm:ss.sssZ`, где:
|
||||
|
||||
Также возможны упрощенные варианты, к примеру:
|
||||
<ul>
|
||||
<li>`YYYY-MM-DD` -- дата в формате год-месяц-день.</li>
|
||||
<li>Обычный символ `T` используется как разделитель.</li>
|
||||
<li>`HH:mm:ss.sss` -- время: часы-минуты-секунды-миллисекунды.</li>
|
||||
<li>Часть `'Z'` обозначает временную зону -- в формате `+-hh:mm`, либо символ `Z`, обозначающий UTC. По стандарту её можно не указывать, тогда UTC, но в Safari с этим ошибка, так что лучше указывать всегда.</li>
|
||||
</ul>
|
||||
|
||||
```js
|
||||
YYYY
|
||||
YYYY-MM
|
||||
YYYY-MM-DD
|
||||
```
|
||||
Также возможны укороченные варианты, например `YYYY-MM-DD` или `YYYY-MM` или даже только `YYYY`.
|
||||
|
||||
Метод `Date.parse(str)` разбирает строку `str` в таком формате и возвращает соответствующее ей количество миллисекунд. Если это невозможно, `Date.parse` возвращает `NaN`.
|
||||
|
||||
На момент написания некоторые браузеры (Safari) воспринимали формат без `'Z'` как дату в локальной таймзоне (по стандарту UTC), поэтому пример ниже в них работает некорректно:
|
||||
Например:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var msNoZone = Date.parse('2012-01-26T13:51:50.417'); // без зоны, значит UTC
|
||||
var msUTC = Date.parse('2012-01-26T13:51:50.417Z'); // зона UTC
|
||||
|
||||
alert(msNoZone); // 1327571510417 (число миллисекунд)
|
||||
|
||||
var msZ = Date.parse('2012-01-26T13:51:50.417z'); // зона z означает UTC
|
||||
alert(msZ == msNoZone); // true, если браузер правильный
|
||||
alert(msUTC); // 1327571510417 (число миллисекунд)
|
||||
```
|
||||
|
||||
С таймзоной `-07:00 GMT` в конце все современные браузеры работают правильно:
|
||||
С таймзоной `-07:00 GMT`:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
|
@ -454,6 +464,7 @@ var ms = Date.parse('2012-01-26T13:51:50.417-07:00');
|
|||
alert(ms); // 1327611110417 (число миллисекунд)
|
||||
```
|
||||
|
||||
|
||||
[smart header="Формат дат для IE8-"]
|
||||
До появления спецификации EcmaScript 5 формат не был стандартизован, и браузеры, включая IE8-, имели свои собственные форматы дат. Частично, эти форматы пересекаются.
|
||||
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
<dd>Строки, такие как `"Мяу"` или пустая строка `""`.</dd>
|
||||
</dl>
|
||||
|
||||
Все остальные значения являются **объектами**, включая функции и массивы.
|
||||
Все остальные значения, включая даты и массивы, являются объектами.
|
||||
|
||||
## Оператор typeof [#type-typeof]
|
||||
|
||||
Оператор `typeof` возвращает тип аргумента. У него есть два синтаксиса:
|
||||
Оператор `typeof` возвращает тип аргумента. У него есть два синтаксиса: со скобками и без:
|
||||
<ol>
|
||||
<li>Синтаксис оператора: `typeof x`.</li>
|
||||
<li>Синтаксис функции: `typeof(x)`.</li>
|
||||
|
@ -91,14 +91,14 @@ alert( typeof new Date ); // 'object'
|
|||
|
||||
Смысл утиной типизации -- в проверке необходимых методов и свойств.
|
||||
|
||||
Например, у нас функция работает с массивами. Мы можем проверить, что объект -- массив, уточнив наличие метода `splice`:
|
||||
Например, у нас функция работает с массивами. Мы можем проверить, что объект -- массив, уточнив наличие метода `splice`, который, как известно, есть у всех массивов:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var something = [1,2,3];
|
||||
var something = [1, 2, 3];
|
||||
|
||||
if (something.splice) {
|
||||
alert('Массив!');
|
||||
alert('Это утка! То есть, массив!');
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -121,16 +121,14 @@ if (x.getTime) {
|
|||
|
||||
## Полиморфизм
|
||||
|
||||
Используем проверку типов для того, чтобы создать полиморфную функцию `sayHi(who)`, которая говорит "Привет" своему аргументу.
|
||||
|
||||
При этом, если передали массив, она должна вызвать себя для каждого подэлемента.
|
||||
Пример полимофрной функции -- `sayHi(who)`, которая будет говорить "Привет" своему аргументу, причём если передан массив -- то "Привет" каждому:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
function sayHi(who) {
|
||||
|
||||
if (who.splice) { // проверка на массив (или что-то похожее)
|
||||
for(var i=0; i<who.length; i++) sayHi(who[i]);
|
||||
if (who.forEach) { // проверка на массив (или что-то похожее)
|
||||
who.forEach(sayHi);
|
||||
} else {
|
||||
alert('Привет, ' + who);
|
||||
}
|
||||
|
@ -141,10 +139,14 @@ sayHi("Вася"); // Привет, Вася
|
|||
|
||||
// Вызов с массивом
|
||||
sayHi( ["Саша", "Петя"] ); // Привет, Саша... Петя
|
||||
|
||||
// Вызов с вложенными массивами
|
||||
sayHi( ["Саша", "Петя", ["Маша", "Юля"] ] ); // Привет Саша..Петя..Маша..Юля
|
||||
```
|
||||
|
||||
Обратите внимание, получилась даже поддержка вложенных массивов :). Да здравствует рекурсия!
|
||||
Здесь вместо `splice` проверяется наличие `forEach`. Так надёжнее, поскольку именно его мы собираемся использовать.
|
||||
|
||||
Обратите внимание, получилась даже поддержка вложенных массивов. Да здравствует рекурсия!
|
||||
|
||||
## Итого
|
||||
|
||||
|
@ -158,5 +160,5 @@ sayHi( ["Саша", "Петя", ["Маша", "Юля"] ] ); // Привет Са
|
|||
<li>Для функций он возвращает `function`, по стандарту функция не считается базовым типом, но на практике это удобно и полезно.</li>
|
||||
</ol>
|
||||
|
||||
Там, где нужно различать объекты, обычно используется утиная типизация, то есть мы смотрим, есть ли в объекте нужный метод, желательно -- тот, который мы собираемся исползовать, но это не обязательно.
|
||||
Там, где нужно различать объекты, обычно используется утиная типизация, то есть мы смотрим, есть ли в объекте нужный метод, желательно -- тот, который мы собираемся использовать.
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ alert( unique(strings) ); // кришна, харе, 8-()
|
|||
<li>Для второго элемента -- это обойдётся в `1` операцию доступа к элементам `result`.</li>
|
||||
<li>Для третьего элемента -- это обойдётся в `2` операции доступа к элементам `result`.</li>
|
||||
<li>...Для n-го элемента -- это обойдётся в `n-1` операций доступа к элементам `result`.</li>
|
||||
</ul>
|
||||
</ol>
|
||||
|
||||
Всего <code>0 + 1 + 2 + ... + n-1 = (n-1)*n/2 = n<sup>2</sup>/2 - n/2</code> (как сумма арифметической прогрессии), то есть количество операций растёт примерно как квадрат от `n`.
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
Метод ["arr.forEach(callback[, thisArg])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach) используется для перебора массива.
|
||||
|
||||
Он позволяет перебрать массив при помощи функции `callback`, что зачастую гораздо элегантнее, нежели цикл `for`.
|
||||
Он позволяет для каждого элемента массива вызывает функцию `callback`.
|
||||
|
||||
Функция `callback` вызывается для каждого элемента с тремя параметрами `callback(item, i, arr)`:
|
||||
Этой функции он передаёт три параметра `callback(item, i, arr)`:
|
||||
|
||||
<ul>
|
||||
<li>`item` -- очередной элемент массива.</li>
|
||||
|
@ -24,16 +24,14 @@
|
|||
//+ run
|
||||
var arr = ["Яблоко", "Апельсин", "Груша"];
|
||||
|
||||
function show(item, i, arr) {
|
||||
arr.forEach(function(item, i, arr) {
|
||||
alert(i + ": " + item + " (массив:" + arr + ")");
|
||||
}
|
||||
|
||||
arr.forEach(show);
|
||||
});
|
||||
```
|
||||
|
||||
Второй, необязательный аргумент `forEach` позволяет указать контекст `this` для `callback`. Мы обсудим его в деталях чуть позже, сейчас он нам не важен.
|
||||
|
||||
Метод `forEach` ничего не возвращает, его используют только для перебора.
|
||||
Метод `forEach` ничего не возвращает, его используют только для перебора, как более "элегантный" вариант, чем обычный цикл `for`.
|
||||
|
||||
## filter
|
||||
|
||||
|
@ -47,12 +45,10 @@ arr.forEach(show);
|
|||
//+ run
|
||||
var arr = [1, -1, 2, -2, 3];
|
||||
|
||||
function isPositive(number) {
|
||||
return number > 0;
|
||||
}
|
||||
|
||||
*!*
|
||||
var positiveArr = arr.filter(isPositive);
|
||||
var positiveArr = arr.filter(function(number) {
|
||||
return number > 0;
|
||||
});
|
||||
*/!*
|
||||
|
||||
alert(positiveArr); // 1,2,3
|
||||
|
@ -68,27 +64,26 @@ alert(positiveArr); // 1,2,3
|
|||
|
||||
```js
|
||||
//+ run
|
||||
var arr = [1, 2, 3, 4];
|
||||
|
||||
function square(number) {
|
||||
return number * number;
|
||||
}
|
||||
var pages = ['a.html', 'b.html', 'c.html'];
|
||||
|
||||
*!*
|
||||
var squaredArr = arr.map(square);
|
||||
var urls = pages.map(function(page) {
|
||||
return 'http://site.com/' + page;
|
||||
});
|
||||
*/!*
|
||||
|
||||
alert(squaredArr); // получили массив квадратов чисел: 1, 4, 9, 16
|
||||
// к каждой строке был прибавлен префикс
|
||||
alert(urls); // http://site.com/a.html, http://site.com/b.html...
|
||||
```
|
||||
|
||||
## every/some
|
||||
|
||||
Эти методы используется для проверки массива.
|
||||
|
||||
Метод ["arr.every(callback[, thisArg])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every) возвращает `true`, если вызов `callback` вернёт `true` для *каждого* элемента `arr`.
|
||||
|
||||
|
||||
Метод ["arr.some(callback[, thisArg])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some) возвращает `true`, если вызов `callback` вернёт `true` для *какого-нибудь* элемента `arr`.
|
||||
<ul>
|
||||
<li>Метод ["arr.every(callback[, thisArg])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every) возвращает `true`, если вызов `callback` вернёт `true` для *каждого* элемента `arr`.</li>
|
||||
<li>Метод ["arr.some(callback[, thisArg])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some) возвращает `true`, если вызов `callback` вернёт `true` для *какого-нибудь* элемента `arr`.</li>
|
||||
</ul>
|
||||
|
||||
```js
|
||||
//+ run
|
||||
|
@ -117,15 +112,17 @@ alert( arr.some(isPositive) ); // true, есть хоть одно положи
|
|||
Аргументы функции `callback(previousValue, currentItem, index, arr)`:
|
||||
|
||||
<ul>
|
||||
<li>`previousValue` -- последний результат вызова функции, он же "промежуточный результат". Значение `previousValue` при первом вызове равно `initialValue` (второй аргумент `reduce`) или, если у `reduce` нет второго аргумента, то оно равно первому элементу массива, а перебор начинается со второго.</li>
|
||||
<li>`previousValue` -- последний результат вызова функции, он же "промежуточный результат".</li>
|
||||
<li>`currentItem` -- текущий элемент массива, элементы перебираются по очереди слева-направо. </li>
|
||||
<li>`index` -- номер текущего элемента.</li>
|
||||
<li>`arr` -- обрабатываемый массив.</li>
|
||||
</ul>
|
||||
|
||||
Разберём работу метода `reduce` на примере.
|
||||
Кроме `callback`, методу можно передать "начальное значение" -- аргумент `initialValue`. Если он есть, то на первом вызове значение `previousValue` будет равно `initialValue`, а если у `reduce` нет второго аргумента, то оно равно первому элементу массива, а перебор начинается со второго.
|
||||
|
||||
Пусть мы хотим вычислить сумму всех элементов массива. Можно сделать это при помощи цикла, но это как раз подходящий повод познакомиться с `reduce`.
|
||||
Проще всего понять работу метода `reduce` на примере.
|
||||
|
||||
Например, в качестве "свёртки" мы хотим получить сумму всех элементов массива.
|
||||
|
||||
Вот решение в одну строку:
|
||||
|
||||
|
@ -133,23 +130,30 @@ alert( arr.some(isPositive) ); // true, есть хоть одно положи
|
|||
//+ run
|
||||
var arr = [1, 2, 3, 4, 5]
|
||||
|
||||
var result = arr.reduce(function(prev, current) { return prev + current }, 0);
|
||||
// для каждого элемента массива запустить функцию,
|
||||
// промежуточный результат передавать первым аргументом далее
|
||||
var result = arr.reduce(function(sum, current) { return sum + current; }, 0);
|
||||
|
||||
alert(result); // 15
|
||||
```
|
||||
|
||||
Разберём, что в нём происходит.
|
||||
|
||||
Здесь начальное значение, с которого начинаются вычисления, равно нулю (второй аргумент `reduce`).
|
||||
При первом запуске `sum` -- исходное значение, с которого начинаются вычисления, равно нулю (второй аргумент `reduce`).
|
||||
|
||||
Сначала анонимная функция вызывается с этим начальным значением и первым элементом массива, результат запоминается и передаётся в следующий вызов, уже со вторым аргументом массива, затем новое значение участвует в вычислениях с третьим аргументом и так далее.
|
||||
|
||||
Таблица вычислений получается такая:
|
||||
Поток вычислений получается такой
|
||||
|
||||
<img src="reduce.svg">
|
||||
|
||||
В виде таблицы где каждая строка -- вызов функции на очередном элементе массива:
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>`prev`</th>
|
||||
<th>`sum`</th>
|
||||
<th>`current`</th>
|
||||
<th>результат</th>
|
||||
</tr>
|
||||
|
@ -188,9 +192,9 @@ alert(result); // 15
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
Функция-аргумент `reduce` могла бы также использовать параметры `i` и `array`, но здесь в них нет нужды.
|
||||
Как видно, результат предыдущего вызова передаётся в первый аргумент следующего.
|
||||
|
||||
**Можно сделать ещё короче!**
|
||||
Кстати, полный набор аргументов функции для `reduce` включает в себя `function(sum, current, i, array)`, то есть номер текущего вызова `i` и весь массив `arr`, но здесь в них нет нужды.
|
||||
|
||||
Посмотрим, что будет, если не указать `initialValue` в вызове `arr.reduce`:
|
||||
|
||||
|
@ -199,7 +203,7 @@ alert(result); // 15
|
|||
var arr = [1, 2, 3, 4, 5]
|
||||
|
||||
// убрали 0 в конце
|
||||
var result = arr.reduce(function(prev, current) { return prev + current });
|
||||
var result = arr.reduce(function(sum, current) { return sum + current });
|
||||
|
||||
alert(result); // 15
|
||||
```
|
||||
|
|
64
1-js/4-data-structures/9-array-iteration/reduce.svg
Normal file
64
1-js/4-data-structures/9-array-iteration/reduce.svg
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="600px" height="105px" viewBox="0 0 600 105" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Slice 1</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="reduce" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<rect id="Rectangle-1" stroke="#979797" sketch:type="MSShapeGroup" x="0" y="65" width="80" height="40"></rect>
|
||||
<text id="1" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="normal" fill="#000000">
|
||||
<tspan x="36" y="90">1</tspan>
|
||||
</text>
|
||||
<text id="sum" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="normal" fill="#000000">
|
||||
<tspan x="7" y="8">sum</tspan>
|
||||
<tspan x="7" y="24">0</tspan>
|
||||
<tspan x="7" y="40">current</tspan>
|
||||
<tspan x="7" y="56">1</tspan>
|
||||
</text>
|
||||
<rect id="Rectangle-2" stroke="#979797" sketch:type="MSShapeGroup" x="79" y="65" width="80" height="40"></rect>
|
||||
<text id="2" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="normal" fill="#000000">
|
||||
<tspan x="115" y="90">2</tspan>
|
||||
</text>
|
||||
<text id="sum" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="normal" fill="#000000">
|
||||
<tspan x="86" y="8">sum</tspan>
|
||||
<tspan x="86" y="24">0+1</tspan>
|
||||
<tspan x="86" y="40">current</tspan>
|
||||
<tspan x="86" y="56">2</tspan>
|
||||
</text>
|
||||
<rect id="Rectangle-3" stroke="#979797" sketch:type="MSShapeGroup" x="158" y="65" width="80" height="40"></rect>
|
||||
<text id="3" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="normal" fill="#000000">
|
||||
<tspan x="194" y="90">3</tspan>
|
||||
</text>
|
||||
<text id="sum" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="normal" fill="#000000">
|
||||
<tspan x="165" y="8">sum</tspan>
|
||||
<tspan x="165" y="24">0+1+2</tspan>
|
||||
<tspan x="165" y="40">current</tspan>
|
||||
<tspan x="165" y="56">3</tspan>
|
||||
</text>
|
||||
<rect id="Rectangle-5" stroke="#979797" sketch:type="MSShapeGroup" x="237" y="65" width="80" height="40"></rect>
|
||||
<text id="4" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="normal" fill="#000000">
|
||||
<tspan x="273" y="90">4</tspan>
|
||||
</text>
|
||||
<text id="sum" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="normal" fill="#000000">
|
||||
<tspan x="244" y="8">sum</tspan>
|
||||
<tspan x="244" y="24">0+1+2+3</tspan>
|
||||
<tspan x="244" y="40">current</tspan>
|
||||
<tspan x="244" y="56">4</tspan>
|
||||
</text>
|
||||
<rect id="Rectangle-4" stroke="#979797" sketch:type="MSShapeGroup" x="316" y="65" width="80" height="40"></rect>
|
||||
<text id="5" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="normal" fill="#000000">
|
||||
<tspan x="352" y="90">5</tspan>
|
||||
</text>
|
||||
<text id="sum" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="normal" fill="#000000">
|
||||
<tspan x="323" y="8">sum</tspan>
|
||||
<tspan x="323" y="24">0+1+2+3+4</tspan>
|
||||
<tspan x="323" y="40">current</tspan>
|
||||
<tspan x="323" y="56">5</tspan>
|
||||
</text>
|
||||
<path d="M412.5,83 L462.5,83" id="Line" stroke="#979797" stroke-width="2" stroke-linecap="square" fill="#979797" sketch:type="MSShapeGroup"></path>
|
||||
<path id="Line-decoration-1" d="M462.5,83 C458.72,81.95 455.48,81.05 451.7,80 C451.7,82.1 451.7,83.9 451.7,86 C455.48,84.95 458.72,84.05 462.5,83 C462.5,83 462.5,83 462.5,83 Z" stroke="#979797" stroke-width="2" stroke-linecap="square" fill="#979797"></path>
|
||||
<text id="0+1+2+3+4+5-=-15" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="normal" fill="#000000">
|
||||
<tspan x="477" y="87">0+1+2+3+4+5 = 15</tspan>
|
||||
</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.2 KiB |
Loading…
Add table
Add a link
Reference in a new issue