beautify 1st part of the tutorial

This commit is contained in:
Ilya Kantor 2015-03-10 12:36:58 +03:00
parent e3dd2cedc0
commit 6444024a9d
327 changed files with 2358 additions and 1986 deletions

View file

@ -19,7 +19,7 @@ alert( "Привет, мир!".length ); // 12
```js
//+ run
var str = "Привет, мир!";
var str = "Привет, мир!";
alert( str.length ); // 12
```
@ -94,8 +94,8 @@ alert( 12.34.toFixed(1) ); // 12.3
...Но если число целое, то будет проблема:
```js
//+ run
alert( 12.toFixed(1) ); // ошибка!
//+ run no-beautify
alert(12.toFixed(1)); // ошибка!
```
Ошибка произойдёт потому, что JavaScript ожидает десятичную дробь после точки.
@ -115,4 +115,4 @@ alert( 12..toFixed(1) ); // 12.0
Почти все значения в JavaScript, кроме разве что `null` и `undefined` имеют их и предоставляют через них разный функционал.
Далее мы подробно разберём основные свойства и методы структур данных в JavaScript.
Далее мы подробно разберём основные свойства и методы структур данных в JavaScript.

View file

@ -3,7 +3,7 @@
```js
//+ run
function f(x) {
alert(arguments.length ? 1 : 0);
alert( arguments.length ? 1 : 0 );
}
f(undefined);

View file

@ -5,7 +5,7 @@
Как в функции отличить отсутствующий аргумент от `undefined`?
```js
function f(x) {
function f(x) {
// ..ваш код..
// выведите 1, если первый аргумент есть, и 0 - если нет
}

View file

@ -5,7 +5,7 @@
function sum() {
var result = 0;
for(var i=0; i<arguments.length; i++) {
for (var i = 0; i < arguments.length; i++) {
result += arguments[i];
}

View file

@ -8,7 +8,7 @@
sum() = 0
sum(1) = 1
sum(1, 2) = 3
sum(1, 2 ,3) = 6
sum(1, 2, 3) = 6
sum(1, 2, 3, 4) = 10
```

View file

@ -6,7 +6,7 @@
Например:
```js
//+ run
//+ run no-beautify
function go(a,b) {
alert("a="+a+", b="+b);
}
@ -25,13 +25,13 @@ function log(a) {
...
}
function log(a,b,c) {
function log(a, b, c) {
...
}
*!*
log(a); // вызовется первая функция
log(a,b,c); // вызовется вторая функция
log(a, b, c); // вызовется вторая функция
*/!*
```
@ -57,12 +57,12 @@ log(a,b,c); // вызовется вторая функция
```js
//+ run
function sayHi() {
for (var i=0; i<arguments.length; i++) {
alert("Привет, " + arguments[i]);
for (var i = 0; i < arguments.length; i++) {
alert( "Привет, " + arguments[i] );
}
}
sayHi("Винни", "Пятачок"); // 'Привет, Винни', 'Привет, Пятачок'
sayHi("Винни", "Пятачок"); // 'Привет, Винни', 'Привет, Пятачок'
```
Все параметры находятся в `arguments`, даже если они есть в списке. Код выше сработал бы также, будь функция объявлена `sayHi(a,b,c)`.
@ -80,8 +80,8 @@ sayHi("Винни", "Пятачок"); // 'Привет, Винни', 'Прив
//+ run
function f(x) {
arguments[0] = 5; // меняет переменную x
alert(x); // 5
}
alert( x ); // 5
}
f(1);
```
@ -91,9 +91,9 @@ f(1);
```js
//+ run
function f(x) {
x = 5;
alert(arguments[0]); // 5, обновленный x
}
x = 5;
alert( arguments[0] ); // 5, обновленный x
}
f(1);
```
@ -106,8 +106,8 @@ function f(x) {
"use strict"; // для браузеров с поддержкой строгого режима
arguments[0] = 5;
alert(x); // не 5, а 1! Переменная "отвязана" от arguments
}
alert( x ); // не 5, а 1! Переменная "отвязана" от arguments
}
f(1);
```
@ -137,7 +137,7 @@ sayHi(1);
```js
//+ run
var args = [];
for(var i=0; i<arguments.length; i++) {
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
```
@ -169,7 +169,7 @@ var vasya = {
surname: 'Петров'
};
var user = {
var user = {
isAdmin: false,
isEmailConfirmed: true
};
@ -180,11 +180,11 @@ var student = {
// добавить к vasya свойства из user и student
*!*
copy(vasya, user, student);
copy(vasya, user, student);
*/!*
alert(vasya.isAdmin); // false
alert(vasya.university); // My university
alert( vasya.isAdmin ); // false
alert( vasya.university ); // My university
```
</li>
@ -207,7 +207,7 @@ var userClone = copy({}, user);
function copy() {
var dst = arguments[0];
for (var i=1; i<arguments.length; i++) {
for (var i = 1; i < arguments.length; i++) {
var arg = arguments[i];
for (var key in arg) {
dst[key] = arg[key];
@ -225,7 +225,7 @@ function copy() {
function copy(dst) {
*/!*
// остальные аргументы остаются безымянными
for (var i=1; i<arguments.length; i++) {
for (var i = 1; i < arguments.length; i++) {
var arg = arguments[i];
for (var key in arg) {
dst[key] = arg[key];
@ -248,7 +248,7 @@ function copy(dst) {
function showWarning(width, height, title, contents) {
width = width || 200; // если не указана width, то width = 200
height = height || 100; // если нет height, то height = 100
title = title || "Предупреждение";
title = title || "Предупреждение";
//...
}
@ -260,9 +260,9 @@ function showWarning(width, height, title, contents) {
```js
function showWarning(width, height, title, contents) {
if (width !== undefined) width = 200;
if (width !== undefined) width = 200;
if (height !== undefined) height = 100;
if (title !== undefined) title = "Предупреждение";
if (title !== undefined) title = "Предупреждение";
//...
}
@ -282,9 +282,9 @@ function showWarning(width, height, title, contents) {
```js
function showWarning(options) {
var width = options.width || 200; // по умолчанию
var width = options.width || 200; // по умолчанию
var height = options.height || 100;
var title = options.title || "Предупреждение";
// ...
@ -296,7 +296,7 @@ showWarning({
Вызвать такую функцию очень легко. Достаточно передать объект аргументов, указав в нем только нужные:
```js
showWarning({
showWarning({
contents: "Вы вызвали функцию" // и всё понятно!
});
```
@ -304,7 +304,7 @@ showWarning({
Сравним это с передачей аргументов через список:
```js
showWarning(null, null, "Предупреждение!");
showWarning(null, null, "Предупреждение!");
// мысль программиста "а что это за null, null в начале? ох, надо глядеть описание функции"
```
@ -315,13 +315,13 @@ showWarning(null, null, "Предупреждение!");
```js
var opts = {
width: 400,
height: 200,
height: 200,
contents: "Текст"
};
showWarning(opts);
opts.contents = "Другой текст";
opts.contents = "Другой текст";
*!*
showWarning(opts); // вызвать с новым текстом, без копирования других аргументов
@ -391,17 +391,17 @@ var factorial = function(n) {
f1();
function f1() {
alert(arguments.callee.caller); // null, меня вызвали из глобального кода
alert( arguments.callee.caller ); // null, меня вызвали из глобального кода
f2();
}
function f2() {
alert(arguments.callee.caller); // f1, функция, из которой меня вызвали
alert( arguments.callee.caller ); // f1, функция, из которой меня вызвали
f3();
}
function f3() {
alert(arguments.callee.caller); // f2, функция, из которой меня вызвали
alert( arguments.callee.caller ); // f2, функция, из которой меня вызвали
}
```

View file

@ -5,6 +5,6 @@
```js
//+ run
var d = new Date(2012, 1, 20, 3, 12);
alert(d);
alert( d );
```

View file

@ -5,12 +5,12 @@
```js
//+ run
function getWeekDay(date) {
var days = ['вс','пн','вт','ср','чт','пт','сб'] ;
var days = ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'];
return days[ date.getDay() ];
return days[date.getDay()];
}
var date = new Date(2014,0,3); // 3 января 2014
alert( getWeekDay(date) ); // 'пт'
var date = new Date(2014, 0, 3); // 3 января 2014
alert( getWeekDay(date) ); // 'пт'
```

View file

@ -7,6 +7,7 @@
Например:
```js
//+ no-beautify
var date = new Date(2012,0,3); // 3 января 2012
alert( getWeekDay(date) ); // Должно вывести 'вт'
```

View file

@ -6,14 +6,14 @@ function getLocalDay(date) {
var day = date.getDay();
if ( day == 0 ) { // день 0 становится 7
day = 7;
if (day == 0) { // день 0 становится 7
day = 7;
}
return day;
}
alert( getLocalDay(new Date(2012,0,3)) ); // 2
alert( getLocalDay(new Date(2012, 0, 3)) ); // 2
```
Если удобнее, чтобы день недели начинался с нуля, то можно возвращать в функции `day - 1`, тогда дни будут от 0 (пн) до 6(вс).

View file

@ -7,6 +7,7 @@
День нужно возвратить в европейской нумерации, т.е. понедельник имеет номер 1, вторник номер 2, ..., воскресенье - номер 7.
```js
//+ no-beautify
var date = new Date(2012, 0, 3); // 3 янв 2012
alert( getLocalDay(date) ); // вторник, выведет 2
```

View file

@ -2,8 +2,8 @@
```js
function getDateAgo(date, days) {
date.setDate( date.getDate() - days );
return date.getDate();
date.setDate(date.getDate() - days);
return date.getDate();
}
```
@ -15,9 +15,9 @@ function getDateAgo(date, days) {
//+ run
function getDateAgo(date, days) {
var dateCopy = new Date(date);
dateCopy.setDate( date.getDate() - days );
return dateCopy.getDate();
dateCopy.setDate(date.getDate() - days);
return dateCopy.getDate();
}
var date = new Date(2015, 0, 2);

View file

@ -3,7 +3,7 @@
```js
//+ run
function getLastDayOfMonth(year, month) {
var date = new Date(year, month+1, 0);
var date = new Date(year, month + 1, 0);
return date.getDate();
}

View file

@ -21,8 +21,8 @@ alert( getSecondsToday() );
```js
//+ run
function getSecondsToday(){
var d = new Date();
return d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds();
function getSecondsToday() {
var d = new Date();
return d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds();
};
```

View file

@ -4,15 +4,15 @@
```js
var dd = date.getDate();
if (dd<10) dd= '0'+dd;
if (dd < 10) dd = '0' + dd;
```
</li>
<li>`date.getMonth()` возвратит месяц, начиная с нуля. Увеличим его на 1:
```js
var mm = date.getMonth() + 1; // месяц 1-12
if (mm<10) mm= '0'+mm;
var mm = date.getMonth() + 1; // месяц 1-12
if (mm < 10) mm = '0' + mm;
```
</li>
@ -20,7 +20,7 @@ if (mm<10) mm= '0'+mm;
```js
var yy = date.getFullYear() % 100;
if (yy<10) yy= '0'+yy;
if (yy < 10) yy = '0' + yy;
```
Заметим, что год, как и другие компоненты, может понадобиться дополнить нулем слева, причем возможно что `yy == 0` (например, 2000 год). При сложении со строкой `0+'0' == '00'`, так что будет все в порядке.
@ -34,18 +34,18 @@ if (yy<10) yy= '0'+yy;
function formatDate(date) {
var dd = date.getDate();
if ( dd < 10 ) dd = '0' + dd;
if (dd < 10) dd = '0' + dd;
var mm = date.getMonth()+1;
if ( mm < 10 ) mm = '0' + mm;
var mm = date.getMonth() + 1;
if (mm < 10) mm = '0' + mm;
var yy = date.getFullYear() % 100;
if ( yy < 10 ) yy = '0' + yy;
if (yy < 10) yy = '0' + yy;
return dd+'.'+mm+'.'+yy;
return dd + '.' + mm + '.' + yy;
}
var d = new Date(2014, 0, 30); // 30 Янв 2014
alert( formatDate(d) ); // '30.01.14'
var d = new Date(2014, 0, 30); // 30 Янв 2014
alert( formatDate(d) ); // '30.01.14'
```

View file

@ -4,45 +4,45 @@
//+ run
function formatDate(date) {
var diff = new Date() - date; // разница в миллисекундах
if (diff < 1000) { // прошло менее 1 секунды
return 'только что';
}
var sec = Math.floor( diff / 1000 ); // округлить diff до секунд
var sec = Math.floor(diff / 1000); // округлить diff до секунд
if (sec < 60) {
return sec + ' сек. назад';
}
var min = Math.floor( diff / 60000 ); // округлить diff до минут
var min = Math.floor(diff / 60000); // округлить diff до минут
if (min < 60) {
return min + ' мин. назад';
return min + ' мин. назад';
}
// форматировать дату, с учетом того, что месяцы начинаются с 0
var d = date;
d = [
'0'+d.getDate(),
'0'+(d.getMonth()+1),
''+d.getFullYear(),
'0'+d.getHours(),
'0'+d.getMinutes()
'0' + d.getDate(),
'0' + (d.getMonth() + 1),
'' + d.getFullYear(),
'0' + d.getHours(),
'0' + d.getMinutes()
];
for(var i=0; i<d.length; i++) {
d[i] = d[i].slice(-2);
for (var i = 0; i < d.length; i++) {
d[i] = d[i].slice(-2);
}
return d.slice(0,3).join('.')+' '+d.slice(3).join(':');
return d.slice(0, 3).join('.') + ' ' + d.slice(3).join(':');
}
alert( formatDate( new Date( new Date - 1) ) ); // только что
alert( formatDate(new Date(new Date - 1)) ); // только что
alert( formatDate( new Date( new Date - 30*1000) ) ); // 30 сек. назад
alert( formatDate(new Date(new Date - 30 * 1000)) ); // 30 сек. назад
alert( formatDate( new Date( new Date- 5*60*1000) ) ); // 5 мин. назад
alert( formatDate(new Date(new Date - 5 * 60 * 1000)) ); // 5 мин. назад
alert( formatDate( new Date( new Date - 86400*1000) ) ); // вчерашняя дата в формате "дд.мм.гг чч:мм"
alert( formatDate(new Date(new Date - 86400 * 1000)) ); // вчерашняя дата в формате "дд.мм.гг чч:мм"
```

View file

@ -15,12 +15,12 @@
```js
function formatDate(date) { /* ваш код */ }
alert( formatDate( new Date(new Date - 1) ) ); // "только что"
alert( formatDate(new Date(new Date - 1)) ); // "только что"
alert( formatDate( new Date(new Date - 30*1000) ) ); // "30 сек. назад"
alert( formatDate(new Date(new Date - 30 * 1000)) ); // "30 сек. назад"
alert( formatDate( new Date(new Date- 5*60*1000) ) ); // "5 мин. назад"
alert( formatDate(new Date(new Date - 5 * 60 * 1000)) ); // "5 мин. назад"
alert( formatDate( new Date(new Date - 86400*1000) ) ); // вчерашняя дата в формате "дд.мм.гг чч:мм"
alert( formatDate(new Date(new Date - 86400 * 1000)) ); // вчерашняя дата в формате "дд.мм.гг чч:мм"
```

View file

@ -13,7 +13,7 @@
```js
//+ run
var now = new Date();
alert(now);
alert( now );
```
</dd>
@ -23,7 +23,7 @@ alert(now);
```js
//+ run
// 24 часа после 01.01.1970 GMT+0
var Jan02_1970 = new Date(3600*24*1000);
var Jan02_1970 = new Date(3600 * 24 * 1000);
alert( Jan02_1970 );
```
@ -50,8 +50,8 @@ new Date(2011, 0, 1); // то же самое, часы/секунды по ум
```js
//+ run
var date = new Date(2011, 0, 1, 2, 3, 4, 567);
alert(date); // 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>
@ -94,11 +94,11 @@ alert(date); // 1.01.2011, 02:03:04.567
var date = new Date();
// час в текущей временной зоне
alert( date.getHours() );
alert( date.getHours() );
// сколько сейчас времени в Лондоне?
// час в зоне GMT+0
alert( date.getUTCHours() );
alert( date.getUTCHours() );
```
Кроме описанных выше, существуют два специальных метода без UTC-варианта:
@ -111,7 +111,7 @@ alert( date.getUTCHours() );
```js
//+ run
alert( new Date().getTimezoneOffset() ); // Для GMT-1 выведет 60
alert( new Date().getTimezoneOffset() ); // Для GMT-1 выведет 60
```
</dd>
@ -141,11 +141,11 @@ alert( new Date().getTimezoneOffset() ); // Для GMT-1 выведет 60
//+ run
var today = new Date;
today.setHours(0);
today.setHours(0);
alert( today ); // сегодня, но час изменён на 0
today.setHours(0, 0, 0, 0);
alert (today ); // сегодня, ровно 00:00:00.
today.setHours(0, 0, 0, 0);
alert( today ); // сегодня, ровно 00:00:00.
```
### Автоисправление даты
@ -166,10 +166,10 @@ alert(d); // ... это 1 февраля 2013!
//+ run
var d = new Date(2011, 1, 28);
*!*
d.setDate( d.getDate() + 2 );
d.setDate(d.getDate() + 2);
*/!*
alert(d); // 2 марта, 2011
alert( d ); // 2 марта, 2011
```
Также это используют для получения даты, отдаленной от имеющейся на нужный промежуток времени. Например, получим дату на 70 секунд большую текущей:
@ -177,9 +177,9 @@ alert(d); // 2 марта, 2011
```js
//+ run
var d = new Date();
d.setSeconds( d.getSeconds()+70);
d.setSeconds(d.getSeconds() + 70);
alert(d); // выведет корректную дату
alert( d ); // выведет корректную дату
```
Можно установить и нулевые, и даже отрицательные компоненты. Например:
@ -189,10 +189,10 @@ alert(d); // выведет корректную дату
var d = new Date;
d.setDate(1); // поставить первое число месяца
alert(d);
alert( d );
d.setDate(0); // нулевого числа нет, будет последнее число предыдущего месяца
alert(d);
alert( d );
```
@ -202,7 +202,7 @@ alert(d);
var d = new Date;
d.setDate(-1); // предпоследнее число предыдущего месяца
alert(d);
alert( d );
```
### Преобразование к числу, разность дат
@ -211,7 +211,7 @@ alert(d);
```js
//+ run
alert( +new Date ) // +date то же самое, что: +date.valueOf()
alert(+new Date) // +date то же самое, что: +date.valueOf()
```
**Важный побочный эффект: даты можно вычитать, результат вычитания объектов `Date` -- их временная разница, в миллисекундах**.
@ -223,13 +223,13 @@ alert( +new Date ) // +date то же самое, что: +date.valueOf()
var start = new Date; // засекли время
// что-то сделать
for (var i=0; i<100000; i++) {
var doSomething = i*i*i;
for (var i = 0; i < 100000; i++) {
var doSomething = i * i * i;
}
var end = new Date; // конец измерения
alert("Цикл занял " + (end-start) + " ms");
alert( "Цикл занял " + (end - start) + " ms" );
```
### Бенчмаркинг
@ -242,11 +242,11 @@ alert("Цикл занял " + (end-start) + " ms");
```js
function walkIn(arr) {
for(var key in arr) arr[i]++
for (var key in arr) arr[i]++
}
function walkLength(arr) {
for(var i=0; i<arr.length; i++) arr[i]++;
for (var i = 0; i < arr.length; i++) arr[i]++;
}
```
@ -259,19 +259,24 @@ function walkLength(arr) {
```js
//+ run
var arr = [];
for(var i=0; i<1000; i++) arr[i] = 0;
for (var i = 0; i < 1000; i++) arr[i] = 0;
function walkIn(arr) { for(var key in arr) arr[i]++; }
function walkLength(arr) { for(var i=0; i<arr.length; i++) arr[i]++; }
function walkIn(arr) {
for (var key in arr) arr[i]++;
}
function walkLength(arr) {
for (var i = 0; i < arr.length; i++) arr[i]++;
}
function bench(f) {
var date = new Date();
for (var i=0; i<10000; i++) f(arr);
for (var i = 0; i < 10000; i++) f(arr);
return new Date() - date;
}
alert('Время walkIn: ' + bench(walkIn) + 'мс');
alert('Время walkLength: ' + bench(walkLength) + 'мс');
alert( 'Время walkIn: ' + bench(walkIn) + 'мс' );
alert( 'Время walkLength: ' + bench(walkLength) + 'мс' );
```
Теперь представим себе, что во время первого бенчмаркинга `bench(walkIn)` компьютер что-то делал параллельно важное (вдруг) и это занимало ресурсы, а во время второго -- перестал. Реальная ситуация? Конечно реальна, особенно на современных ОС, где много процессов одновременно.
@ -281,28 +286,34 @@ alert('Время walkLength: ' + bench(walkLength) + 'мс');
```js
//+ run
var arr = [];
for(var i=0; i<1000; i++) arr[i] = 0;
for (var i = 0; i < 1000; i++) arr[i] = 0;
function walkIn(arr) { for(var key in arr) arr[i]++; }
function walkLength(arr) { for(var i=0; i<arr.length; i++) arr[i]++; }
function walkIn(arr) {
for (var key in arr) arr[i]++;
}
function walkLength(arr) {
for (var i = 0; i < arr.length; i++) arr[i]++;
}
function bench(f) {
var date = new Date();
for (var i=0; i<1000; i++) f(arr);
for (var i = 0; i < 1000; i++) f(arr);
return new Date() - date;
}
*!*
// bench для каждого теста запустим много раз, чередуя
var timeIn = 0, timeLength = 0;
for(var i=0; i<100; i++) {
var timeIn = 0,
timeLength = 0;
for (var i = 0; i < 100; i++) {
timeIn += bench(walkIn);
timeLength += bench(walkLength);
}
*/!*
alert('Время walkIn: ' + timeIn + 'мс');
alert('Время walkLength: ' +timeLength + 'мс');
alert( 'Время walkIn: ' + timeIn + 'мс' );
alert( 'Время walkLength: ' + timeLength + 'мс' );
```
[smart header="Более точное время с `performance.now()`"]
@ -328,13 +339,18 @@ alert('Время walkLength: ' +timeLength + 'мс');
```js
//+ run
var arr = [];
for(var i=0; i<1000; i++) arr[i] = 0;
for (var i = 0; i < 1000; i++) arr[i] = 0;
function walkIn(arr) { for(var key in arr) arr[i]++; }
function walkLength(arr) { for(var i=0; i<arr.length; i++) arr[i]++; }
function walkIn(arr) {
for (var key in arr) arr[i]++;
}
function walkLength(arr) {
for (var i = 0; i < arr.length; i++) arr[i]++;
}
function bench(f) {
for (var i=0; i<10000; i++) f(arr);
for (var i = 0; i < 10000; i++) f(arr);
}
console.time("All Benchmarks");
@ -452,7 +468,7 @@ alert( d.toISOString() ); // вывод, похожий на '2011-01-26T13:51:5
//+ run
var msUTC = Date.parse('2012-01-26T13:51:50.417Z'); // зона UTC
alert(msUTC); // 1327571510417 (число миллисекунд)
alert( msUTC ); // 1327571510417 (число миллисекунд)
```
С таймзоной `-07:00 GMT`:
@ -461,7 +477,7 @@ alert(msUTC); // 1327571510417 (число миллисекунд)
//+ run
var ms = Date.parse('2012-01-26T13:51:50.417-07:00');
alert(ms); // 1327611110417 (число миллисекунд)
alert( ms ); // 1327611110417 (число миллисекунд)
```
@ -474,7 +490,7 @@ alert(ms); // 1327611110417 (число миллисекунд)
//+ run
var ms = Date.parse("January 26, 2011 13:51:50");
alert(ms);
alert( ms );
```
Вы также можете почитать о старых форматах IE в документации к методу <a href="http://msdn.microsoft.com/en-us/library/k4w173wk%28v=vs.85%29.aspx">MSDN Date.parse</a>.

View file

@ -4,10 +4,10 @@
```js
//+ run
alert(typeof 123); // "number"
alert(typeof "строка"); // "string"
alert(typeof new Date()); // "object"
alert(typeof []); // "object"
alert( typeof 123 ); // "number"
alert( typeof "строка" ); // "string"
alert( typeof new Date() ); // "object"
alert( typeof [] ); // "object"
```
Оператор `typeof` не умеет различать разные типы объектов, они для него все на одно лицо: `"object"`. Поэтому он не сможет отличить `Date` от `Array`.
@ -21,12 +21,12 @@ alert(typeof []); // "object"
function formatDate(date) {
if (typeof date == 'number') {
// перевести секунды в миллисекунды и преобразовать к Date
date = new Date(date*1000);
} else if(typeof date == 'string') {
date = new Date(date * 1000);
} else if (typeof date == 'string') {
// разобрать строку и преобразовать к Date
date = date.split('-');
date = new Date(date[0], date[1]-1, date[2]);
} else if ( date.length ) { // есть длина, но не строка - значит массив
date = new Date(date[0], date[1] - 1, date[2]);
} else if (date.length) { // есть длина, но не строка - значит массив
date = new Date(date[0], date[1], date[2]);
}
// преобразования для поддержки полиморфизма завершены,
@ -35,21 +35,21 @@ function formatDate(date) {
var day = date.getDate();
if (day < 10) day = '0' + day;
var month = date.getMonth()+1;
var month = date.getMonth() + 1;
if (month < 10) month = '0' + month;
// взять 2 последние цифры года
var year = date.getFullYear() % 100;
var year = date.getFullYear() % 100;
if (year < 10) year = '0' + year;
var formattedDate = day + '.' + month + '.' + year;
return formattedDate;
}
alert( formatDate( '2011-10-02' ) ); // 02.10.11
alert( formatDate( 1234567890 ) ); // 14.02.09
alert( formatDate( [2014,0,1] ) ); // 01.01.14
alert( formatDate( new Date(2014,0,1) ) ); // 01.01.14
alert( formatDate('2011-10-02') ); // 02.10.11
alert( formatDate(1234567890) ); // 14.02.09
alert( formatDate([2014, 0, 1]) ); // 01.01.14
alert( formatDate(new Date(2014, 0, 1)) ); // 01.01.14
```

View file

@ -18,9 +18,9 @@
```js
function formatDate(date) { /* ваш код */ }
alert( formatDate( '2011-10-02' ) ); // 02.10.11
alert( formatDate( 1234567890 ) ); // 14.02.09
alert( formatDate( [2014,0,1] ) ); // 01.01.14
alert( formatDate( new Date(2014,0,1) ) ); // 01.01.14
alert( formatDate('2011-10-02') ); // 02.10.11
alert( formatDate(1234567890) ); // 14.02.09
alert( formatDate([2014, 0, 1]) ); // 01.01.14
alert( formatDate(new Date(2014, 0, 1)) ); // 01.01.14
```

View file

@ -36,8 +36,8 @@
```js
typeof undefined // "undefined"
typeof 0 // "number"
typeof 0 // "number"
typeof true // "boolean"
typeof "foo" // "string"
@ -45,7 +45,7 @@ typeof "foo" // "string"
typeof {} // "object"
*!*
typeof null // "object"
typeof null // "object"
*/!*
function f() { /* ... */ }
@ -63,7 +63,7 @@ typeof f // "function"
```js
//+ run
var x = null;
x.prop = 1; // ошибка, т.к. нельзя присвоить свойство примитиву
x.prop = 1; // ошибка, т.к. нельзя присвоить свойство примитиву
```
</li>
@ -98,7 +98,7 @@ alert( typeof new Date ); // 'object'
var something = [1, 2, 3];
if (something.splice) {
alert('Это утка! То есть, массив!');
alert( 'Это утка! То есть, массив!' );
}
```
@ -111,7 +111,7 @@ if (something.splice) {
var x = new Date();
if (x.getTime) {
alert('Дата!');
alert( 'Дата!' );
}
```
@ -130,7 +130,7 @@ function sayHi(who) {
if (who.forEach) { // проверка на массив (или что-то похожее)
who.forEach(sayHi);
} else {
alert('Привет, ' + who);
alert( 'Привет, ' + who );
}
}
@ -138,10 +138,10 @@ function sayHi(who) {
sayHi("Вася"); // Привет, Вася
// Вызов с массивом
sayHi( ["Саша", "Петя"] ); // Привет, Саша... Петя
sayHi(["Саша", "Петя"]); // Привет, Саша... Петя
// Вызов с вложенными массивами
sayHi( ["Саша", "Петя", ["Маша", "Юля"] ] ); // Привет Саша..Петя..Маша..Юля
sayHi(["Саша", "Петя", ["Маша", "Юля"]]); // Привет Саша..Петя..Маша..Юля
```
Здесь вместо `splice` проверяется наличие `forEach`. Так надёжнее, поскольку именно его мы собираемся использовать.

View file

@ -4,7 +4,7 @@
<li>При операциях, когда необходимо получить окончательный результат -- округлять до 2го знака после запятой. Все, что дальше -- ошибка округления:
```js
//+ run
//+ run no-beautify
var price1 = 0.1, price2 = 0.2;
alert( +(price1 + price2).toFixed(2) );
```

View file

@ -5,9 +5,9 @@
```js
//+ run
var i = 0;
while(i < 11) {
while (i < 11) {
i += 0.2;
if (i>9.8 && i<10.2) alert(i);
if (i > 9.8 && i < 10.2) alert( i );
}
```

View file

@ -6,7 +6,7 @@
```js
var i = 0;
while(i != 10) {
while (i != 10) {
i += 0.2;
}
```

View file

@ -72,7 +72,7 @@ function getDecimal(num) {
var str = "" + num;
var zeroPos = str.indexOf(".");
if (zeroPos == -1) return 0;
str = str.slice( zeroPos );
str = str.slice(zeroPos);
return +str;
}

View file

@ -5,13 +5,15 @@
function fibBinet(n) {
var phi = (1 + Math.sqrt(5)) / 2;
// используем Math.round для округления до ближайшего целого
return Math.round( Math.pow(phi, n) / Math.sqrt(5) );
return Math.round(Math.pow(phi, n) / Math.sqrt(5));
}
function fib(n){
var a=1, b=0, x;
for(i=0; i<n; i++) {
x = a+b;
function fib(n) {
var a = 1,
b = 0,
x;
for (i = 0; i < n; i++) {
x = a + b;
a = b
b = x;
}
@ -21,7 +23,7 @@ function fib(n){
alert( fibBinet(2) ); // 1, равно fib(2)
alert( fibBinet(8) ); // 21, равно fib(8)
*!*
alert( fibBinet(77)); // 5527939700884755
alert( fibBinet(77) ); // 5527939700884755
alert( fib(77) ); // 5527939700884757, не совпадает!
*/!*
```

View file

@ -9,10 +9,12 @@
Код для их вычисления (из задачи [](/task/fibonacci-numbers)):
```js
function fib(n){
var a=1, b=0, x;
for(i=0; i<n; i++) {
x = a+b;
function fib(n) {
var a = 1,
b = 0,
x;
for (i = 0; i < n; i++) {
x = a + b;
a = b
b = x;
}

View file

@ -4,6 +4,6 @@
//+ run
var max = 10;
alert( Math.random()*max );
alert( Math.random() * max );
```

View file

@ -2,8 +2,9 @@
```js
//+ run
var min=5, max = 10;
var min = 5,
max = 10;
alert( min + Math.random()*(max-min) );
alert( min + Math.random() * (max - min) );
```

View file

@ -5,7 +5,7 @@
```js
//+ run
function randomInteger(min, max) {
var rand = min + Math.random()*(max-min)
var rand = min + Math.random() * (max - min)
rand = Math.round(rand);
return rand;
}
@ -20,6 +20,7 @@ alert( randomInteger(1, 3) );
Это происходит из-за того, что `Math.round()` получает разнообразные случайные числа из интервала от `1` до `3`, но при округлении до ближайшего целого получится, что:
```js
//+ no-beautify
значения из диапазона 1 ... 1.49999.. станут 1
значения из диапазона 1.5 ... 2.49999.. станут 2
значения из диапазона 2.5 ... 2.99999.. станут 3
@ -35,10 +36,10 @@ alert( randomInteger(1, 3) );
//+ run
*!*
function randomInteger(min, max) {
var rand = min - 0.5 + Math.random()*(max-min+1)
rand = Math.round(rand);
return rand;
}
var rand = min - 0.5 + Math.random() * (max - min + 1)
rand = Math.round(rand);
return rand;
}
*/!*
alert( randomInteger(5, 10) );
@ -55,6 +56,7 @@ alert( randomInteger(5, 10) );
Тогда `Math.floor()` округлит их так:
```js
//+ no-beautify
1 ... 1.999+ станет 1
2 ... 2.999+ станет 2
3 ... 3.999+ станет 3
@ -67,10 +69,10 @@ alert( randomInteger(5, 10) );
//+ run
*!*
function randomInteger(min, max) {
var rand = min + Math.random() * (max+1-min);
rand = Math.floor(rand);
return rand;
}
var rand = min + Math.random() * (max + 1 - min);
rand = Math.floor(rand);
return rand;
}
*/!*
alert( randomInteger(5, 10) );

View file

@ -21,7 +21,7 @@ alert( 010 ); // 8 в восьмеричной системе
```js
//+ run
// еще пример научной формы: 3 с 5 нулями
alert( 3e5 ); // 300000
alert( 3e5 ); // 300000
```
Если количество нулей отрицательно, то число сдвигается вправо за десятичную точку, так что получается десятичная дробь:
@ -44,8 +44,8 @@ alert( 3e-5 ); // 0.00003 <-- 5 нулей, включая начальный
```js
//+ run
alert(1/0); // Infinity
alert(12345/0); // Infinity
alert( 1 / 0 ); // Infinity
alert( 12345 / 0 ); // Infinity
```
**`Infinity` -- особенное численное значение, которое ведет себя в точности как математическая бесконечность `∞`.**
@ -56,8 +56,8 @@ alert(12345/0); // Infinity
```js
//+ run
alert(Infinity > 1234567890); // true
alert(Infinity + 5 == Infinity); // true
alert( Infinity > 1234567890 ); // true
alert( Infinity + 5 == Infinity ); // true
```
**Бесконечность можно присвоить и в явном виде: `var x = Infinity`.**
@ -84,7 +84,7 @@ alert( 1e500 ); // Infinity
```js
//+ run
alert( 0 / 0 ); // NaN
alert( 0 / 0 ); // NaN
```
Значение `NaN` используется для обозначения математической ошибки и обладает следующими свойствами:
@ -96,8 +96,8 @@ alert( 0 / 0 ); // NaN
```js
//+ run
if (NaN == NaN) alert("=="); // Ни один вызов
if (NaN === NaN) alert("==="); // не сработает
if (NaN == NaN) alert( "==" ); // Ни один вызов
if (NaN === NaN) alert( "===" ); // не сработает
```
</li>
@ -105,7 +105,7 @@ if (NaN === NaN) alert("==="); // не сработает
```js
//+ run
var n = 0/0;
var n = 0 / 0;
alert( isNaN(n) ); // true
```
@ -115,9 +115,9 @@ alert( isNaN(n) ); // true
```js
//+ run
var n = 0/0;
var n = 0 / 0;
if (n !== n) alert('n = NaN!');
if (n !== n) alert( 'n = NaN!' );
```
Это работает, но для наглядности лучше использовать `isNaN(n)`.
@ -156,7 +156,7 @@ var value = prompt("Введите Infinity", 'Infinity');
var number = +value;
*/!*
alert(number); // Infinity, плюс преобразовал строку "Infinity" к такому "числу"
alert( number ); // Infinity, плюс преобразовал строку "Infinity" к такому "числу"
```
Обычно если мы хотим от посетителя получить число, то `Infinity` или `NaN` нам не подходят. Для того, чтобы отличить "обычные" числа от таких специальных значений, существует функция `isFinite`.
@ -178,23 +178,23 @@ alert( isFinite(NaN) ); // false
```js
//+ run
var s = "12.34";
alert( +s ); // 12.34
var s = "12.34";
alert( +s ); // 12.34
```
При этом, если строка не является в точности числом, то результат будет `NaN`:
```js
//+ run
alert( +"12test" ); // NaN
alert( +"12test" ); // NaN
```
Единственное исключение -- пробельные символы в начале и в конце строки, которые игнорируются:
```js
//+ run
alert( +" -12"); // -12
alert( +" \n34 \n"); // 34, перевод строки \n является пробельным символом
alert( +" -12" ); // -12
alert( +" \n34 \n" ); // 34, перевод строки \n является пробельным символом
alert( +"" ); // 0, пустая строка становится нулем
alert( +"1 2" ); // NaN, пробел посередине числа - ошибка
```
@ -203,7 +203,7 @@ alert( +"1 2" ); // NaN, пробел посередине числа - ошиб
```js
//+ run
alert( '12.34' / "-2" ); // -6.17
alert( '12.34' / "-2" ); // -6.17
```
## Мягкое преобразование: parseInt и parseFloat
@ -214,7 +214,7 @@ alert( '12.34' / "-2" ); // -6.17
```js
//+ run
alert( +"12px" ) // NaN
alert(+"12px") // NaN
```
Для удобного чтения таких значений существует функция `parseInt`:
@ -230,8 +230,8 @@ alert( parseInt('12px') ); // 12
```js
//+ run
alert( parseInt('12px') ) // 12, ошибка на символе 'p'
alert( parseFloat('12.3.4') ) // 12.3, ошибка на второй точке
alert(parseInt('12px')) // 12, ошибка на символе 'p'
alert(parseFloat('12.3.4')) // 12.3, ошибка на второй точке
```
Конечно, существуют ситуации, когда `parseInt/parseFloat` возвращают `NaN`. Это происходит при ошибке на первом же символе:
@ -253,9 +253,9 @@ alert( parseInt('a123') ); // NaN
var x = prompt("Введите значение", "-11.5");
if (isNaN(x)) {
alert("Строка преобразовалась в NaN. Не число");
alert( "Строка преобразовалась в NaN. Не число" );
} else {
alert("Число");
alert( "Число" );
}
```
@ -349,7 +349,7 @@ alert( n.toString(36) ); // kf12oi
</dl>
```js
//+ run
//+ run no-beautify
alert( Math.floor(3.1) ); // 3
alert( Math.ceil(3.1) ); // 4
alert( Math.round(3.1) ); // 3
@ -362,15 +362,15 @@ alert( Math.round(3.1) ); // 3
```js
//+ run
alert( ~~12.3 ); // 12
alert( ~~12.3 ); // 12
```
Любая побитовая операция такого рода подойдет, например XOR (исключающее ИЛИ, `"^"`) с нулем:
```js
//+ run
alert( 12.3 ^ 0 ); // 12
alert( 1.2 + 1.3 ^ 0); // 2, приоритет ^ меньше, чем +
alert( 12.3 ^ 0 ); // 12
alert( 1.2 + 1.3 ^ 0 ); // 2, приоритет ^ меньше, чем +
```
Это удобно в первую очередь тем, что легко читается и не заставляет ставить дополнительные скобки как `Math.floor(...)`:
@ -388,7 +388,7 @@ var x = a * b / c ^ 0; // читается как "a * b / c и округлит
```js
//+ run
var n = 3.456;
alert( Math.round( n * 100 ) / 100 ); // 3.456 -> 345.6 -> 346 -> 3.46
alert( Math.round(n * 100) / 100 ); // 3.456 -> 345.6 -> 346 -> 3.46
```
Таким образом можно округлять число и вверх и вниз.
@ -448,7 +448,7 @@ alert( Math.round(price * 10) / 10 ); // 6.4
```js
//+ run
alert(0.1 + 0.2 == 0.3);
alert( 0.1 + 0.2 == 0.3 );
```
Запустили? Если нет -- все же сделайте это.
@ -459,14 +459,14 @@ alert(0.1 + 0.2 == 0.3);
```js
//+ run
alert(0.1 + 0.2); // 0.30000000000000004
alert( 0.1 + 0.2 ); // 0.30000000000000004
```
Как видите, произошла небольшая вычислительная ошибка, результат сложения `0.1 + 0.2` немного больше, чем `0.3`.
```js
//+ run
alert(0.1 + 0.2 > 0.3); // true
alert( 0.1 + 0.2 > 0.3 ); // true
```
Всё дело в том, что в стандарте IEEE 754 на число выделяется ровно 8 байт(=64 бита), не больше и не меньше.
@ -477,7 +477,7 @@ alert(0.1 + 0.2 > 0.3); // true
```js
//+ run
alert( 0.1.toFixed(20) ); // 0.10000000000000000555
alert( 0.1.toFixed(20) ); // 0.10000000000000000555
```
Когда мы складываем `0.1` и `0.2`, то две неточности складываются, получаем незначительную, но всё же ошибку в вычислениях.
@ -490,7 +490,7 @@ alert( 0.1.toFixed(20) ); // 0.10000000000000000555
```js
//+ run
alert( (0.1*10 + 0.2*10) / 10 ); // 0.3
alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
```
Это работает, т.к. числа `0.1*10 = 1` и `0.2*10 = 2` могут быть точно представлены в двоичной системе.
@ -513,7 +513,7 @@ alert( +result.toFixed(10) ); // 0.3
```js
//+ run
alert(9999999999999999); // выведет 10000000000000000
alert( 9999999999999999 ); // выведет 10000000000000000
```
Причина та же -- потеря точности.
@ -581,7 +581,7 @@ JavaScript предоставляет базовые тригонометрич
//+ run
var number = 123456789;
alert( number.toLocaleString() ); // 123 456 789
alert( number.toLocaleString() ); // 123 456 789
```
Его поддерживают все современные браузеры, кроме IE10- (для которых нужно подключить библиотеку [Intl.JS](https://github.com/andyearnshaw/Intl.js/)). Он также умеет форматировать валюту и проценты. Более подробно про устройство этого метода можно будет узнать в статье [](/intl), когда это вам понадобится.

View file

@ -16,7 +16,7 @@ var newStr = str[0].toUpperCase() + str.slice(1);
//+ run
function ucFirst(str) {
// только пустая строка в логическом контексте даст false
if (!str) return str;
if (!str) return str;
return str[0].toUpperCase() + str.slice(1);
}

View file

@ -5,7 +5,7 @@
Напишите функцию `ucFirst(str)`, которая возвращает строку `str` с заглавным первым символом, например:
```js
ucFirst("вася") == "Вася";
ucFirst("вася") == "Вася";
ucFirst("") == ""; // нет ошибок при пустой строке
```

View file

@ -11,8 +11,8 @@ function truncate(str, maxlength) {
return str;
}
alert(truncate("Вот, что мне хотелось бы сказать на эту тему:", 20));
alert(truncate("Всем привет!", 20));
alert( truncate("Вот, что мне хотелось бы сказать на эту тему:", 20) );
alert( truncate("Всем привет!", 20) );
```
Можно было бы написать этот код ещё короче:
@ -20,7 +20,7 @@ alert(truncate("Всем привет!", 20));
```js
//+ run
function truncate(str, maxlength) {
return (str.length > maxlength) ?
return (str.length > maxlength) ?
str.slice(0, maxlength - 3) + '...' : str;
}
```

View file

@ -26,7 +26,7 @@ var str = "012345";
```js
//+ run
alert('Привет\nМир'); // выведет "Мир" на новой строке
alert( 'Привет\nМир' ); // выведет "Мир" на новой строке
```
Есть и более редкие символы, вот их список:
@ -56,7 +56,7 @@ var str = '*!*I\'m*/!* a JavaScript programmer';
```js
//+ run
var str = "I'm a JavaScript \"programmer\" ";
alert(str); // I'm a JavaScript "programmer"
alert( str ); // I'm a JavaScript "programmer"
```
Экранирование служит исключительно для правильного восприятия строки JavaScript. В памяти строка будет содержать сам символ без `'\'`. Вы можете увидеть это, запустив пример выше.
@ -67,7 +67,7 @@ alert(str); // I'm a JavaScript "programmer"
//+ run
var str = ' символ \\ ';
alert(str); // символ \
alert( str ); // символ \
```
Заэкранировать можно любой символ. Если он не специальный, то ничего не произойдёт:
@ -75,7 +75,7 @@ alert(str); // символ \
```js
//+ run
alert( "\a" ); // a
// идентично alert( "a" );
// идентично alert( "a" );
```
## Методы и свойства
@ -91,7 +91,7 @@ alert( "\a" ); // a
//+ run
var str = "My\n"; // 3 символа. Третий - перевод строки
alert(str.length); // 3
alert( str.length ); // 3
```
### Доступ к символам
@ -101,7 +101,7 @@ alert(str.length); // 3
```js
//+ run
var str = "jQuery";
alert( str.charAt(0) ); // "j"
alert( str.charAt(0) ); // "j"
```
В JavaScript **нет отдельного типа "символ"**, так что `charAt` возвращает строку, состоящую из выбранного символа.
@ -111,7 +111,7 @@ alert( str.charAt(0) ); // "j"
```js
//+ run
var str = "Я - современный браузер!";
alert(str[0]); // "Я", IE8+
alert( str[0] ); // "Я", IE8+
```
Разница между этим способом и `charAt` заключается в том, что если символа нет -- `charAt` выдает пустую строку, а скобки -- `undefined`:
@ -119,7 +119,7 @@ alert(str[0]); // "Я", IE8+
```js
//+ run
alert( "".charAt(0) ); // пустая строка
alert( ""[0] ); // undefined, IE8+
alert( "" [0] ); // undefined, IE8+
```
Вообще же метод `charAt` существует по историческим причинам, ведь квадратные скобки -- проще и короче.
@ -143,9 +143,9 @@ alert( ""[0] ); // undefined, IE8+
//+ run
var str = "строка";
str = str[3] + str[4] + str[5];
str = str[3] + str[4] + str[5];
alert(str); // ока
alert( str ); // ока
```
### Смена регистра
@ -160,7 +160,7 @@ alert( "Интерфейс".toUpperCase() ); // ИНТЕРФЕЙС
Пример ниже получает первый символ и приводит его к нижнему регистру:
```js
alert( "Интерфейс"[0].toLowerCase() ); // 'и'
alert( "Интерфейс" [0].toLowerCase() ); // 'и'
```
### Поиск подстроки
@ -184,7 +184,7 @@ alert( str.indexOf("widget") ); // -1, не найдено, так как пои
//+ run
var str = "Widget with id";
alert( str.indexOf("id", 2) ) // 12, поиск начат с позиции 2
alert(str.indexOf("id", 2)) // 12, поиск начат с позиции 2
```
Также существует аналогичный метод <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/lastIndexOf">lastIndexOf</a>, который ищет не с начала, а с конца строки.
@ -214,8 +214,8 @@ alert( ~-1 ); // -(-1+1) = 0
//+ run
var str = "Widget";
if( ~str.indexOf("get") ) {
alert('совпадение есть!');
if (~str.indexOf("get")) {
alert( 'совпадение есть!' );
}
```
@ -235,14 +235,14 @@ if( ~str.indexOf("get") ) {
```js
//+ run
var str = "Ослик Иа-Иа посмотрел на виадук"; // ищем в этой строке
var target = "Иа"; // цель поиска
var target = "Иа"; // цель поиска
var pos = 0;
while(true) {
while (true) {
var foundPos = str.indexOf(target, pos);
if (foundPos == -1) break;
if (foundPos == -1) break;
alert(foundPos); // нашли на этой позиции
alert( foundPos ); // нашли на этой позиции
pos = foundPos + 1; // продолжить поиск со следующей
}
```
@ -254,12 +254,12 @@ while(true) {
```js
//+ run
var str = "Ослик Иа-Иа посмотрел на виадук"; // ищем в этой строке
var target = "Иа"; // цель поиска
var target = "Иа"; // цель поиска
*!*
var pos = -1;
while ( (pos = str.indexOf(target, pos+1)) != -1) {
alert(pos);
while ((pos = str.indexOf(target, pos + 1)) != -1) {
alert( pos );
}
*/!*
```
@ -313,14 +313,14 @@ alert(str)
```js
//+ run
alert( "testme".substring(-2) ); // "testme", -2 становится 0
alert( "testme".substring(-2) ); // "testme", -2 становится 0
```
Кроме того, если <code>start &gt; end</code>, то аргументы меняются местами, т.е. возвращается участок строки *между* `start` и `end`:
```js
//+ run
alert( "testme".substring(4, -1) ); // "test"
alert( "testme".substring(4, -1) ); // "test"
// -1 становится 0 -> получили substring(4, 0)
// 4 > 0, так что аргументы меняются местами -> substring(0, 4) = "test"
```
@ -331,7 +331,7 @@ alert( "testme".substring(4, -1) ); // "test"
```js
//+ run
alert( "testme".slice(-2) ); // "me", от 2 позиции с конца
alert( "testme".slice(-2) ); // "me", от 2 позиции с конца
```
@ -416,10 +416,10 @@ alert( "абрикос".charCodeAt(0) ); // 1072, код 'а'
```js
//+ run
var str = '';
for (var i=1034; i<=1113; i++) {
for (var i = 1034; i <= 1113; i++) {
str += String.fromCharCode(i);
}
alert(str);
alert( str );
```
Результат:
@ -479,7 +479,7 @@ alert( "ö" > "z" ); // true
```js
"Вася" > "Ваня" // true, т.к. начальные символы совпадают, а потом 'с' > 'н'
"Дома" > "До" // true, т.к. начало совпадает, но в 1й строке больше символов
"Дома" > "До" // true, т.к. начало совпадает, но в 1й строке больше символов
```
[warn header="Числа в виде строк сравниваются как строки"]
@ -488,14 +488,14 @@ alert( "ö" > "z" ); // true
```js
//+ run
alert("2" > "14"); // true, так как это строки, и для первых символов верно "2" > "1"
alert( "2" > "14" ); // true, так как это строки, и для первых символов верно "2" > "1"
```
Если хотя бы один аргумент -- не строка, то другой будет преобразован к числу:
```js
//+ run
alert(2 > "14"); // false
alert( 2 > "14" ); // false
```
[/warn]

View file

@ -25,7 +25,7 @@
```js
1. o = new Object();
2. o = {}; // пустые фигурные скобки
2. o = {}; // пустые фигурные скобки
```
Обычно все пользуются синтаксисом `(2)`, т.к. он короче.
@ -50,9 +50,9 @@ var person = {}; // пока пустой
```js
// при присвоении свойства в объекте автоматически создаётся "ящик"
// с именем "name" и в него записывается содержимое 'Вася'
person.name = 'Вася';
person.name = 'Вася';
person.age = 25; // запишем ещё одно свойство: с именем 'age' и значением 25
person.age = 25; // запишем ещё одно свойство: с именем 'age' и значением 25
```
<img src="object-person-1.svg">
@ -61,7 +61,7 @@ person.age = 25; // запишем ещё одно свойство: с име
Чтобы прочитать их -- также обратимся через точку:
```js
alert(person.name + ': ' + person.age); // "Вася: 25"
alert( person.name + ': ' + person.age ); // "Вася: 25"
```
Удаление осуществляется оператором `delete`:
@ -84,8 +84,8 @@ delete person.age;
Его синтаксис: `"prop" in obj`, причем имя свойства -- в виде строки, например:
```js
if ("name" in person) {
alert("Свойство name существует!");
if ("name" in person) {
alert( "Свойство name существует!" );
}
```
@ -99,17 +99,19 @@ if ("name" in person) {
//+ run
var person = {};
alert(person.lalala); // undefined, нет свойства с ключом lalala
alert( person.lalala ); // undefined, нет свойства с ключом lalala
```
Таким образом **мы можем легко проверить существование свойства -- получив его и сравнив с `undefined`**:
```js
//+ run
var person = { name: "Василий" };
var person = {
name: "Василий"
};
alert(person.lalala === undefined); // true, свойства нет
alert(person.name === undefined); // false, свойство есть.
alert( person.lalala === undefined ); // true, свойства нет
alert( person.name === undefined ); // false, свойство есть.
```
[smart header="Разница между проверками `in` и `=== undefined`"]
@ -127,8 +129,8 @@ obj.test = undefined; // добавили свойство со значение
*!*
// проверим наличие свойств test и заведомо отсутствующего blabla
alert(obj.test === undefined); // true
alert(obj.blabla === undefined); // true
alert( obj.test === undefined ); // true
alert( obj.blabla === undefined ); // true
*/!*
```
@ -185,10 +187,12 @@ person.любимый стиль музыки = 'Джаз'; // ??? ошибка
```js
//+ run
var person = { age: 25 };
var person = {
age: 25
};
var key = 'age';
alert( person[key] ); // выведет person['age']
alert( person[key] ); // выведет person['age']
```
Вообще, если имя свойства хранится в переменной (`var key = "age"`), то единственный способ к нему обратиться -- это квадратные скобки `person[key]`.
@ -203,9 +207,9 @@ alert( person[key] ); // выведет person['age']
```js
var menuSetup = {
width: 300,
height: 200,
title: "Menu"
width: 300,
height: 200,
title: "Menu"
};
// то же самое, что:
@ -222,9 +226,9 @@ menuSetup.title = 'Menu';
```js
var menuSetup = {
width: 300,
'height': 200,
"мама мыла раму": true
width: 300,
'height': 200,
"мама мыла раму": true
};
```
@ -232,7 +236,7 @@ var menuSetup = {
```js
var user = {
name: "Таня",
name: "Таня",
age: 25,
*!*
size: {
@ -243,9 +247,9 @@ var user = {
*/!*
}
alert( user.name ) // "Таня"
alert(user.name) // "Таня"
alert( user.size.top ) // 90
alert(user.size.top) // 90
```
Здесь значением свойства `size` является объект `{top: 90, middle: 60, bottom: 90 }`.
@ -275,6 +279,7 @@ var user = {
Например, есть много объектов с полями `name` и `age`:
```js
//+ no-beautify
{name: "Вася", age: 25}
{name: "Петя", age: 22}
{name: "Маша", age: 19}
@ -284,6 +289,7 @@ var user = {
Для их эффективного хранения будет создана структура, которая описывает данный вид объектов. Выглядеть она будет примерно так: `<string name, number age>`. А сами объекты будут представлены в памяти только данными:
```js
//+ no-beautify
<структура: string name, number age>
Вася 25
Петя 22
@ -316,7 +322,7 @@ user.isAdmin = true;
<li>Через переменную, в которой хранится ключ:
```js
var key = "prop";
var key = "prop";
obj[key] = 5
```

View file

@ -2,8 +2,8 @@
```js
//+ run
function isEmpty(obj) {
for(var key in obj) {
function isEmpty(obj) {
for (var key in obj) {
return false;
}
return true;
@ -11,10 +11,10 @@ function isEmpty(obj) {
var schedule = {};
alert( isEmpty( schedule ) ); // true
alert( isEmpty(schedule) ); // true
schedule["8:30"] = "подъём";
alert( isEmpty( schedule ) ); // false
alert( isEmpty(schedule) ); // false
```

View file

@ -7,16 +7,16 @@
Работать должно так:
```js
function isEmpty(obj) {
function isEmpty(obj) {
/* ваш код */
}
var schedule = {};
alert( isEmpty( schedule ) ); // true
alert( isEmpty(schedule) ); // true
schedule["8:30"] = "подъём";
alert( isEmpty( schedule ) ); // false
alert( isEmpty(schedule) ); // false
```

View file

@ -5,16 +5,16 @@
"use strict";
var salaries = {
"Вася": 100,
"Петя": 300,
"Даша": 250
"Вася": 100,
"Петя": 300,
"Даша": 250
};
var sum = 0;
for(var name in salaries) {
for (var name in salaries) {
sum += salaries[name];
}
alert(sum);
alert( sum );
```

View file

@ -12,9 +12,9 @@
"use strict";
var salaries = {
"Вася": 100,
"Петя": 300,
"Даша": 250
"Вася": 100,
"Петя": 300,
"Даша": 250
};
//... ваш код выведет 650

View file

@ -5,20 +5,20 @@
"use strict";
var salaries = {
"Вася": 100,
"Петя": 300,
"Даша": 250
"Вася": 100,
"Петя": 300,
"Даша": 250
};
var max = 0;
var maxName = "";
for(var name in salaries) {
for (var name in salaries) {
if (max < salaries[name]) {
max = salaries[name];
maxName = name;
}
}
alert(maxName || "нет сотрудников");
alert( maxName || "нет сотрудников" );
```

View file

@ -12,9 +12,9 @@
"use strict";
var salaries = {
"Вася": 100,
"Петя": 300,
"Даша": 250
"Вася": 100,
"Петя": 300,
"Даша": 250
};
// ... ваш код выведет "Петя"

View file

@ -8,13 +8,13 @@ var menu = {
title: "My menu"
};
function isNumeric(n) {
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function multiplyNumeric(obj) {
for(var key in obj) {
if (isNumeric( obj[key] )) {
for (var key in obj) {
if (isNumeric(obj[key])) {
obj[key] *= 2;
}
}
@ -22,6 +22,6 @@ function multiplyNumeric(obj) {
multiplyNumeric(menu);
alert("menu width="+menu.width+" height="+menu.height+" title="+menu.title);
alert( "menu width=" + menu.width + " height=" + menu.height + " title=" + menu.title );
```

View file

@ -7,25 +7,25 @@
```js
// до вызова
var menu = {
width: 200,
height: 300,
title: "My menu"
width: 200,
height: 300,
title: "My menu"
};
multiplyNumeric(menu);
// после вызова
menu = {
width: 400,
height: 600,
title: "My menu"
width: 400,
height: 600,
title: "My menu"
};
```
P.S. Для проверки на число используйте функцию:
```js
function isNumeric(n) {
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n)
}
```

View file

@ -9,7 +9,7 @@
Синтаксис:
```js
for (key in obj) {
for (key in obj) {
/* ... делать что-то с obj[key] ... */
}
```
@ -33,17 +33,17 @@ for (*!*var key*/!* in menu) {
```js
//+ run
var menu = {
width: 300,
height: 200,
title: "Menu"
width: 300,
height: 200,
title: "Menu"
};
for (var key in menu) {
// этот код будет вызван для каждого свойства объекта
// ..и выведет имя свойства и его значение
for (var key in menu) {
// этот код будет вызван для каждого свойства объекта
// ..и выведет имя свойства и его значение
*!*
alert("Ключ: " + key + " значение:" + menu[key]);
alert( "Ключ: " + key + " значение:" + menu[key] );
*/!*
}
```
@ -61,9 +61,9 @@ for (var key in menu) {
```js
//+ run
var menu = {
width: 300,
height: 200,
title: "Menu"
width: 300,
height: 200,
title: "Menu"
};
*!*
@ -74,7 +74,7 @@ for (var key in menu) {
}
*/!*
alert("Всего свойств: " + counter);
alert( "Всего свойств: " + counter );
```
В следующих главах мы пройдём массивы и познакомимся с другим, более коротким, вызовом: `Object.keys(menu).length`.
@ -119,7 +119,7 @@ user.age = 25;
// порядок перебора соответствует порядку присвоения свойства
*/!*
for (var prop in user) {
alert(prop); // name, surname, age
alert( prop ); // name, surname, age
}
```
@ -134,7 +134,7 @@ var codes = {
"1": "США"
};
for(var code in codes) alert(code); // 1, 7, 38
for (var code in codes) alert( code ); // 1, 7, 38
```
При запуске этого кода в современном браузере мы увидим, что на первое место попал код США!
@ -148,15 +148,15 @@ for(var code in codes) alert(code); // 1, 7, 38
```js
//+ run
var codes = {
"+7": "Россия",
"+7": "Россия",
"+38": "Украина",
"+1": "США"
};
for (var code in codes ) {
for (var code in codes) {
var value = codes[code];
code = +code; // ..если нам нужно именно число, преобразуем: "+7" -> 7
alert( code + ": " + value ); // 7, 38, 1 во всех браузерах
}
```

View file

@ -26,7 +26,9 @@ var phrase = message;
Вот как выглядит переменная, которой присвоен объект:
```js
var user = { name: "Вася" };
var user = {
name: "Вася"
};
```
<img src="variable-contains-reference.svg">
@ -38,6 +40,7 @@ var user = { name: "Вася" };
Например:
```js
//+ no-beautify
var user = { name: "Вася" }; // в переменной - ссылка
var admin = user; // скопировали ссылку
@ -78,14 +81,14 @@ alert(*!*user.name*/!*); // 'Петя', изменения видны в user
//+ run
var user = {
name: "Вася",
age: 30
age: 30
};
*!*
var clone = {}; // новый пустой объект
// скопируем в него все свойства user
for(var key in user) {
for (var key in user) {
clone[key] = user[key];
}
*/!*
@ -93,7 +96,7 @@ for(var key in user) {
// теперь clone - полностью независимая копия
clone.name = "Петя"; // поменяли данные в clone
alert(user.name); // по-прежнем "Вася"
alert( user.name ); // по-прежнем "Вася"
```
В этом коде каждое свойство объекта `user` копируется в `clone`. Если предположить, что они примитивны, то каждое скопируется по значению и мы как раз получим полный клон.
@ -116,7 +119,7 @@ var time = {
microsecond: 123456
}
console.log(time); // (*)
console.log(time); // (*)
time.microsecond++; // (**)
console.log(time);

View file

@ -11,6 +11,6 @@ var fruits = ["Яблоко", "Груша", "Слива"];
То есть, для массива длины `goods`:
```js
var lastItem = goods[goods.length-1]; // получить последний элемент
var lastItem = goods[goods.length - 1]; // получить последний элемент
```

View file

@ -4,6 +4,7 @@
Например, для `[-1, 2, 3, -9, 11]`:
```js
//+ no-beautify
// Начиная с -1:
-1
-1 + 2
@ -41,9 +42,9 @@
function getMaxSubSum(arr) {
var maxSum = 0; // если совсем не брать элементов, то сумма 0
for(var i=0; i<arr.length; i++) {
for (var i = 0; i < arr.length; i++) {
var sumFixedStart = 0;
for(var j=i; j<arr.length; j++) {
for (var j = i; j < arr.length; j++) {
sumFixedStart += arr[j];
maxSum = Math.max(maxSum, sumFixedStart);
}
@ -76,8 +77,9 @@ alert( getMaxSubSum([100, -9, 2, -3, 5]) ); // 100
```js
//+ run
function getMaxSubSum(arr) {
var maxSum = 0, partialSum = 0;
for (var i=0; i<arr.length; i++) {
var maxSum = 0,
partialSum = 0;
for (var i = 0; i < arr.length; i++) {
partialSum += arr[i];
maxSum = Math.max(maxSum, partialSum);
if (partialSum < 0) partialSum = 0;

View file

@ -4,8 +4,8 @@
//+ run
var styles = ["Джаз", "Блюз"];
styles.push("Рок-н-Ролл");
styles[styles.length-2] = "Классика";
styles[styles.length - 2] = "Классика";
alert( styles.shift() );
styles.unshift( "Рэп", "Регги ");
styles.unshift("Рэп", "Регги ");
```

View file

@ -14,6 +14,7 @@
Массив в результате каждого шага:
```js
//+ no-beautify
Джаз, Блюз
Джаз, Блюз, Рок-н-Ролл
Джаз, Классика, Рок-н-Ролл

View file

@ -4,8 +4,8 @@
//+ run
var arr = ["Яблоко", "Апельсин", "Груша", "Лимон"];
var rand = Math.floor( Math.random() * arr.length );
var rand = Math.floor(Math.random() * arr.length);
alert(arr[rand]);
alert( arr[rand] );
```

View file

@ -11,6 +11,6 @@ var arr = ["Яблоко", "Апельсин", "Груша", "Лимон"];
P.S. Код для генерации случайного целого от `min` to `max` включительно:
```js
var rand = min + Math.floor( Math.random() * (max+1-min) );
var rand = min + Math.floor(Math.random() * (max + 1 - min));
```

View file

@ -4,20 +4,20 @@
//+ run demo
var numbers = [];
while(true) {
while (true) {
var value = prompt("Введите число", 0);
if (value === "" || value === null || isNaN(value)) break;
numbers.push(+value);
}
var sum = 0;
for(var i=0; i<numbers.length; i++) {
for (var i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
alert(sum);
alert( sum );
```

View file

@ -2,13 +2,13 @@
```js
//+ run
var arr = [1,2,3];
var arr = [1, 2, 3];
var arr2 = arr; // (*)
arr2[0] = 5;
alert(arr[0]);
alert(arr2[0]);
alert( arr[0] );
alert( arr2[0] );
```
Код выведет `5` в обоих случаях, так как массив является объектом. В строке `(*)` в переменную `arr2` копируется ссылка на него, а сам объект в памяти по-прежнему один, в нём отражаются изменения, внесенные через `arr2` или `arr`.
@ -19,6 +19,6 @@ alert(arr2[0]);
```js
var arr2 = [];
for(var i=0; i<arr.length; i++) arr2[i] = arr[i];
for (var i = 0; i < arr.length; i++) arr2[i] = arr[i];
```

View file

@ -5,14 +5,14 @@
Что выведет этот код?
```js
var arr = [1,2,3];
var arr = [1, 2, 3];
var arr2 = arr;
arr2[0] = 5;
*!*
alert(arr[0]);
alert(arr2[0]);
alert( arr[0] );
alert( arr2[0] );
*/!*
```

View file

@ -3,10 +3,10 @@
```js
function find(array, value) {
for(var i=0; i<array.length; i++) {
for (var i = 0; i < array.length; i++) {
if (array[i] == value) return i;
}
return -1;
}
```
@ -22,10 +22,10 @@ function find(array, value) {
return array.indexOf(value);
}
for(var i=0; i<array.length; i++) {
for (var i = 0; i < array.length; i++) {
if (array[i] === value) return i;
}
return -1;
}
@ -33,14 +33,14 @@ var arr = ["a", -1, 2, "b"];
var index = find(arr, 2);
alert(index);
alert( index );
```
... Но еще лучшим вариантом было бы определить `find` по-разному в зависимости от поддержки браузером метода `indexOf`:
```js
// создаем пустой массив и проверяем поддерживается ли indexOf
if ( [].indexOf ) {
if ([].indexOf) {
var find = function(array, value) {
return array.indexOf(value);
@ -48,10 +48,10 @@ if ( [].indexOf ) {
} else {
var find = function(array, value) {
for(var i=0; i<array.length; i++) {
for (var i = 0; i < array.length; i++) {
if (array[i] === value) return i;
}
return -1;
}

View file

@ -7,7 +7,7 @@
Например:
```js
arr = [ "test", 2, 1.5, false ];
arr = ["test", 2, 1.5, false];
find(arr, "test"); // 0
find(arr, 2); // 1

View file

@ -12,7 +12,7 @@
function filterRange(arr, a, b) {
var result = [];
for(var i=0; i<arr.length; i++) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] >= a && arr[i] <= b) {
result.push(arr[i]);
}
@ -24,6 +24,6 @@ function filterRange(arr, a, b) {
var arr = [5, 4, 3, 8, 0];
var filtered = filterRange(arr, 3, 5);
alert(filtered);
alert( filtered );
```

View file

@ -5,7 +5,7 @@
// шаг 1
var arr = [];
for (var i=2; i<100; i++) {
for (var i = 2; i < 100; i++) {
arr[i] = true
}
@ -14,27 +14,27 @@ var p = 2;
do {
// шаг 3
for (i=2*p; i<100; i+=p) {
for (i = 2 * p; i < 100; i += p) {
arr[i] = false;
}
// шаг 4
for (i=p+1; i<100; i++) {
for (i = p + 1; i < 100; i++) {
if (arr[i]) break;
}
p = i;
} while (p*p < 100); // шаг 5
} while (p * p < 100); // шаг 5
// шаг 6 (готово)
// посчитать сумму
var sum = 0;
for (i=0; i<arr.length; i++) {
for (i = 0; i < arr.length; i++) {
if (arr[i]) {
sum += i;
}
}
alert(sum);
alert( sum );
```

View file

@ -30,9 +30,9 @@ var fruits = ["Яблоко", "Апельсин", "Слива"];
//+ run
var fruits = ["Яблоко", "Апельсин", "Слива"];
alert(fruits[0]); // Яблоко
alert(fruits[1]); // Апельсин
alert(fruits[2]); // Слива
alert( fruits[0] ); // Яблоко
alert( fruits[1] ); // Апельсин
alert( fruits[2] ); // Слива
```
Элемент можно всегда заменить:
@ -51,9 +51,9 @@ fruits[3] = 'Лимон'; // теперь ["Яблоко", "Апельсин", "
```js
//+ run
var fruits = ["Яблоко", "Апельсин", "Груша"];
var fruits = ["Яблоко", "Апельсин", "Груша"];
alert(fruits.length); // 3
alert( fruits.length ); // 3
```
**Через `alert` можно вывести и массив целиком.**
@ -62,9 +62,9 @@ alert(fruits.length); // 3
```js
//+ run
var fruits = ["Яблоко", "Апельсин", "Груша"];
var fruits = ["Яблоко", "Апельсин", "Груша"];
alert(fruits); // Яблоко,Апельсин,Груша
alert( fruits ); // Яблоко,Апельсин,Груша
```
**В массиве может храниться любое число элементов любого типа.**
@ -72,7 +72,7 @@ alert(fruits); // Яблоко,Апельсин,Груша
В том числе, строки, числа, объекты, вот например:
```js
//+ run
//+ run no-beautify
// микс значений
var arr = [ 1, 'Имя', { name: 'Петя' }, true ];
@ -108,7 +108,7 @@ var fruits = ["Яблоко", "Апельсин", "Груша"];
alert( fruits.pop() ); // удалили "Груша"
alert(fruits); // Яблоко, Апельсин
alert( fruits ); // Яблоко, Апельсин
```
</dd>
@ -121,7 +121,7 @@ var fruits = ["Яблоко", "Апельсин"];
fruits.push("Груша");
alert(fruits); // Яблоко, Апельсин, Груша
alert( fruits ); // Яблоко, Апельсин, Груша
```
Является полным аналогом `fruits[fruits.length] = ...`.
@ -139,7 +139,7 @@ var fruits = ["Яблоко", "Апельсин", "Груша"];
alert( fruits.shift() ); // удалили Яблоко
alert(fruits); // Апельсин, Груша
alert( fruits ); // Апельсин, Груша
```
</dd>
@ -151,7 +151,7 @@ var fruits = ["Апельсин", "Груша"];
fruits.unshift('Яблоко');
alert(fruits); // Яблоко, Апельсин, Груша
alert( fruits ); // Яблоко, Апельсин, Груша
```
</dd>
@ -167,7 +167,7 @@ fruits.push("Апельсин", "Персик");
fruits.unshift("Ананас", "Лимон");
// результат: ["Ананас", "Лимон", "Яблоко", "Апельсин", "Персик"]
alert(fruits);
alert( fruits );
```
## Внутреннее устройство массива
@ -184,10 +184,10 @@ function eat(arr) {
var arr = ["нам", "не", "страшен", "серый", "волк"]
alert(arr.length); // 5
alert( arr.length ); // 5
eat(arr);
eat(arr);
alert(arr.length); // 3, в функцию массив не скопирован, а передана ссылка
alert( arr.length ); // 3, в функцию массив не скопирован, а передана ссылка
```
**Ещё одно следствие -- можно присваивать в массив любые свойства.**
@ -215,7 +215,7 @@ var a = [];
a[0] = 0;
a[5] = 5;
alert(a); // 0,,,,,5
alert( a ); // 0,,,,,5
```
Эти запятые появляются потому, что алгоритм вывода массива идёт от `0` до `arr.length` и выводит всё через запятую. Отсутствие значений даёт несколько запятых подряд.
@ -254,7 +254,7 @@ fruits.shift(); // убрать 1 элемент с начала
Действия при операции:
```js
fruits.pop(); // убрать 1 элемент с конца
fruits.pop(); // убрать 1 элемент с конца
```
<img src="array-pop.svg">
@ -273,7 +273,7 @@ fruits.pop(); // убрать 1 элемент с конца
var arr = ["Яблоко", "Апельсин", "Груша"];
*!*
for (var i=0; i<arr.length; i++) {
for (var i = 0; i < arr.length; i++) {
alert( arr[i] );
}
*/!*
@ -339,13 +339,13 @@ alert(arr.length); // *!*1001*/!*
```js
//+ run
var arr = [1, 2, 3, 4, 5];
var arr = [1, 2, 3, 4, 5];
arr.length = 2; // укоротить до 2 элементов
alert(arr); // [1, 2]
alert( arr ); // [1, 2]
arr.length = 5; // вернуть length обратно, как было
alert(arr[3]); // undefined: значения не вернулись
alert( arr[3] ); // undefined: значения не вернулись
```
Самый простой способ очистить массив -- это `arr.length=0`.
@ -367,12 +367,12 @@ var arr = *!*new Array*/!*("Яблоко", "Груша", "и т.п.");
```js
//+ run
var arr = new Array(2, 3);
alert(arr[0]); // 2, создан массив [2, 3], всё ок
var arr = new Array(2, 3);
alert( arr[0] ); // 2, создан массив [2, 3], всё ок
*!*
arr = new Array(2); // создаст массив [2] ?
alert(arr[0]); // undefined! у нас массив без элементов, длины 2
alert( arr[0] ); // undefined! у нас массив без элементов, длины 2
*/!*
```
@ -394,7 +394,7 @@ var matrix = [
[7, 8, 9]
];
alert(matrix[1][1]); // центральный элемент
alert( matrix[1][1] ); // центральный элемент
```
## Внутреннее представление массивов
@ -428,10 +428,10 @@ alert(matrix[1][1]); // центральный элемент
```js
// предпочтительное
var arr = [ элемент1, элемент2... ];
var arr = [элемент1, элемент2...];
// new Array
var arr = new Array( элемент1, элемент2...);
var arr = new Array(элемент1, элемент2...);
```
При этом `new Array(число)` создаёт массив заданной длины, *без элементов*. Чтобы избежать ошибок, предпочтителен первый синтаксис.

View file

@ -6,21 +6,23 @@
function addClass(obj, cls) {
var classes = obj.className ? obj.className.split(' ') : [];
for(var i=0; i<classes.length; i++) {
for (var i = 0; i < classes.length; i++) {
if (classes[i] == cls) return; // класс уже есть
}
classes.push(cls); // добавить
obj.className = classes.join(' '); // и обновить свойство
}
var obj = { className: 'open menu' };
var obj = {
className: 'open menu'
};
addClass(obj, 'new');
addClass(obj, 'open');
addClass(obj, 'me');
alert(obj.className) // open menu new me
alert(obj.className) // open menu new me
```
P.S. "Альтернативный" подход к проверке наличия класса вызовом `obj.className.indexOf(cls)` был бы неверным. В частности, он найдёт `cls = "menu"` в строке классов `obj.className = "open mymenu"`.

View file

@ -14,10 +14,10 @@ var obj = {
```js
addClass(obj, 'new'); // obj.className='open menu new'
addClass(obj, 'open'); // без изменений (класс уже существует)
addClass(obj, 'open'); // без изменений (класс уже существует)
addClass(obj, 'me'); // obj.className='open menu new me'
alert(obj.className); // "open menu new me"
alert( obj.className ); // "open menu new me"
```
P.S. Ваша функция не должна добавлять лишних пробелов.

View file

@ -20,7 +20,7 @@ function aclean(arr) {
// этот объект будем использовать для уникальности
var obj = {};
for(var i=0; i<arr.length; i++) {
for (var i = 0; i < arr.length; i++) {
// разбить строку на буквы, отсортировать и слить обратно
*!*
var sorted = arr[i].toLowerCase().split('').sort().join(''); // (*)
@ -32,7 +32,7 @@ function aclean(arr) {
var result = [];
// теперь в obj находится для каждого ключа ровно одно значение
for(var key in obj) result.push(obj[key]);
for (var key in obj) result.push(obj[key]);
return result;
}
@ -48,10 +48,10 @@ alert( aclean(arr) );
```js
var sorted = arr[i] // ЗОВ
.toLowerCase() // зов
.split('') // ['з','о','в']
.sort() // ['в','з','о']
.join(''); // взо
.toLowerCase() // зов
.split('') // ['з','о','в']
.sort() // ['в','з','о']
.join(''); // взо
```
Получится, что два разных слова `'ЗОВ'` и `'воз'` получат одинаковую отсортированную форму `'взо'`.

View file

@ -11,19 +11,20 @@ function unique(arr) {
var result = [];
nextInput:
for(var i=0; i<arr.length; i++) {
var str = arr[i]; // для каждого элемента
for(var j=0; j<result.length; j++) { // ищем, был ли он уже?
if (result[j] == str) continue nextInput; // если да, то следующий
for (var i = 0; i < arr.length; i++) {
var str = arr[i]; // для каждого элемента
for (var j = 0; j < result.length; j++) { // ищем, был ли он уже?
if (result[j] == str) continue nextInput; // если да, то следующий
}
result.push(str);
}
result.push(str);
}
return result;
}
var strings = ["кришна", "кришна", "харе", "харе",
"харе", "харе", "кришна", "кришна", "8-()"];
var strings = ["кришна", "кришна", "харе", "харе",
"харе", "харе", "кришна", "кришна", "8-()"
];
alert( unique(strings) ); // кришна, харе, 8-()
```
@ -62,18 +63,19 @@ alert( unique(strings) ); // кришна, харе, 8-()
function unique(arr) {
var obj = {};
for(var i=0; i<arr.length; i++) {
for (var i = 0; i < arr.length; i++) {
var str = arr[i];
*!*
obj[str] = true; // запомнить строку в виде свойства объекта
*/!*
}
return Object.keys(obj); // или собрать ключи перебором для IE8-
}
var strings = ["кришна", "кришна", "харе", "харе",
"харе", "харе", "кришна", "кришна", "8-()"];
var strings = ["кришна", "кришна", "харе", "харе",
"харе", "харе", "кришна", "кришна", "8-()"
];
alert( unique(strings) ); // кришна, харе, 8-()
```

View file

@ -13,8 +13,9 @@ function unique(arr) {
/* ваш код */
}
var strings = ["кришна", "кришна", "харе", "харе",
"харе", "харе", "кришна", "кришна", "8-()"];
var strings = ["кришна", "кришна", "харе", "харе",
"харе", "харе", "кришна", "кришна", "8-()"
];
alert( unique(strings) ); // кришна, харе, 8-()
```

View file

@ -11,7 +11,7 @@
function camelize(str) {
var arr = str.split('-');
for(var i=1; i<arr.length; i++) {
for (var i = 1; i < arr.length; i++) {
// преобразовать: первый символ с большой буквы
arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1);
}
@ -19,8 +19,8 @@ function camelize(str) {
return arr.join('');
}
alert( camelize("background-color")); // backgroundColor
alert( camelize("list-style-image") ); // listStyleImage
alert( camelize("background-color") ); // backgroundColor
alert( camelize("list-style-image") ); // listStyleImage
alert( camelize("-webkit-transition") ); // WebkitTransition
```

View file

@ -4,8 +4,8 @@
//+ run
function removeClass(obj, cls) {
var classes = obj.className.split(' ');
for(i=0; i<classes.length; i++) {
for (i = 0; i < classes.length; i++) {
if (classes[i] == cls) {
classes.splice(i, 1); // удалить класс
*!*
@ -14,14 +14,16 @@ function removeClass(obj, cls) {
}
}
obj.className = classes.join(' ');
}
var obj = { className: 'open menu menu' }
var obj = {
className: 'open menu menu'
}
removeClass(obj, 'blabla');
removeClass(obj, 'blabla');
removeClass(obj, 'menu')
alert(obj.className) // open
alert(obj.className) // open
```
В примере выше есть тонкий момент. Элементы массива проверяются один за другим. При вызове `splice` удаляется текущий, `i-й` элемент, и те элементы, которые идут дальше, сдвигаются на его место.

View file

@ -5,7 +5,7 @@
У объекта есть свойство `className`, которое хранит список "классов" - слов, разделенных пробелами:
```js
var obj = {
var obj = {
className: 'open menu'
};
```
@ -20,9 +20,11 @@ removeClass(obj, 'blabla'); // без изменений (нет такого к
P.S. Дополнительное усложнение. Функция должна корректно обрабатывать дублирование класса в строке:
```js
obj = { className: 'my menu menu' };
obj = {
className: 'my menu menu'
};
removeClass(obj, 'menu');
alert(obj.className); // 'my'
alert( obj.className ); // 'my'
```
Лишних пробелов после функции образовываться не должно.

View file

@ -4,18 +4,18 @@
//+ run
function filterRangeInPlace(arr, a, b) {
for(var i = 0; i<arr.length; i++) {
var val = arr[i];
if (val < a || val > b) {
arr.splice(i--, 1);
}
for (var i = 0; i < arr.length; i++) {
var val = arr[i];
if (val < a || val > b) {
arr.splice(i--, 1);
}
}
}
var arr = [5, 3, 8, 1];
filterRangeInPlace(arr, 1, 4);
alert(arr); // [3, 1]
alert( arr ); // [3, 1]
```

View file

@ -12,6 +12,6 @@ arr = [5, 3, 8, 1];
filterRangeInPlace(arr, 1, 4); // удалены числа вне диапазона 1..4
alert(arr); // массив изменился: остались [3, 1]
alert( arr ); // массив изменился: остались [3, 1]
```

View file

@ -2,7 +2,7 @@
```js
//+ run
var arr = [ 5, 2, 1, -10, 8];
var arr = [5, 2, 1, -10, 8];
function compareReversed(a, b) {
return b - a;
@ -10,6 +10,6 @@ function compareReversed(a, b) {
arr.sort(compareReversed);
alert(arr);
alert( arr );
```

View file

@ -5,10 +5,10 @@
Как отсортировать массив чисел в обратном порядке?
```js
var arr = [ 5, 2, 1, -10, 8];
var arr = [5, 2, 1, -10, 8];
// отсортируйте?
alert(arr); // 8, 5, 2, 1, -10
alert( arr ); // 8, 5, 2, 1, -10
```

View file

@ -2,13 +2,13 @@
```js
//+ run
var arr = [ "HTML", "JavaScript", "CSS" ];
var arr = ["HTML", "JavaScript", "CSS"];
*!*
var arrSorted = arr.slice().sort();
*/!*
alert(arrSorted);
alert(arr);
alert( arrSorted );
alert( arr );
```

View file

@ -7,12 +7,12 @@
Исходный массив не должен меняться.
```js
var arr = [ "HTML", "JavaScript", "CSS" ];
var arr = ["HTML", "JavaScript", "CSS"];
// ... ваш код ...
alert(arrSorted); // CSS, HTML, JavaScript
alert(arr); // HTML, JavaScript, CSS (без изменений)
alert( arrSorted ); // CSS, HTML, JavaScript
alert( arr ); // HTML, JavaScript, CSS (без изменений)
```
Постарайтесь сделать код как можно короче.

View file

@ -11,13 +11,13 @@
var arr = [1, 2, 3, 4, 5];
*!*
function compareRandom(a, b) {
function compareRandom(a, b) {
return Math.random() - 0.5;
}
arr.sort(compareRandom);
*/!*
alert(arr); // элементы в случайном порядке, например [3,5,1,2,4]
alert( arr ); // элементы в случайном порядке, например [3,5,1,2,4]
```

View file

@ -9,6 +9,6 @@ var arr = [1, 2, 3, 4, 5];
arr.sort(ваша функция);
alert(arr); // элементы в случайном порядке, например [3,5,1,2,4]
alert( arr ); // элементы в случайном порядке, например [3,5,1,2,4]
```

View file

@ -1,7 +1,7 @@
Для сортировки объявим и передадим в `sort` анонимную функцию, которая сравнивает объекты по полю `age`:
```js
//+ run
//+ run no-beautify
*!*
// Наша функция сравнения
function compareAge(personA, personB) {

View file

@ -7,6 +7,7 @@
Например:
```js
//+ no-beautify
var vasya = { name: "Вася", age: 23 };
var masha = { name: "Маша", age: 18 };
var vovochka = { name: "Вовочка", age: 6 };

View file

@ -3,10 +3,14 @@
```js
//+ run
var list = {
value: 1, next: {
value: 2, next: {
value: 3, next: {
value: 4, next: null
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null
}
}
}
@ -15,7 +19,7 @@ var list = {
function printList(list) {
var tmp = list;
while(tmp) {
while (tmp) {
alert( tmp.value );
tmp = tmp.next;
}
@ -49,23 +53,27 @@ function printList(list) {
```js
//+ run
var list = {
value: 1, next: {
value: 2, next: {
value: 3, next: {
value: 4, next: null
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null
}
}
}
};
function printList(list) {
alert(list.value); // (1)
alert( list.value ); // (1)
if (list.next) {
printList(list.next); // (2)
}
}
printList(list);
@ -78,10 +86,14 @@ printList(list);
```js
//+ run
var list = {
value: 1, next: {
value: 2, next: {
value: 3, next: {
value: 4, next: null
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null
}
}
}
@ -93,7 +105,7 @@ function printReverseList(list) {
printReverseList(list.next);
}
alert(list.value);
alert( list.value );
}
printReverseList(list);
@ -104,10 +116,14 @@ printReverseList(list);
```js
//+ run
var list = {
value: 1, next: {
value: 2, next: {
value: 3, next: {
value: 4, next: null
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null
}
}
}
@ -118,12 +134,12 @@ function printReverseList(list) {
var arr = [];
var tmp = list;
while(tmp) {
while (tmp) {
arr.push(tmp.value);
tmp = tmp.next;
}
for( var i = arr.length-1; i>=0; i-- ) {
for (var i = arr.length - 1; i >= 0; i--) {
alert( arr[i] );
}
}

View file

@ -28,6 +28,7 @@ var list = {
Альтернативный способ создания:
```js
//+ no-beautify
var list = { value: 1 };
list.next = { value: 2 };
list.next.next = { value: 3 };

View file

@ -15,8 +15,8 @@ var names = 'Маша, Петя, Марина, Василий';
var arr = names.split(', ');
for (var i=0; i<arr.length; i++) {
alert('Вам сообщение ' + arr[i]);
for (var i = 0; i < arr.length; i++) {
alert( 'Вам сообщение ' + arr[i] );
}
```
@ -54,7 +54,7 @@ var arr = ['Маша', 'Петя', 'Марина', 'Василий'];
var str = arr.join(';');
alert(str); // Маша;Петя;Марина;Василий
alert( str ); // Маша;Петя;Марина;Василий
```
[smart header="new Array + join = Повторение строки"]
@ -82,7 +82,7 @@ var arr = ["Я", "иду", "домой"];
delete arr[1]; // значение с индексом 1 удалено
// теперь arr = ["Я", undefined, "домой"];
alert(arr[1]); // undefined
alert( arr[1] ); // undefined
```
Да, элемент удален из массива, но не так, как нам этого хочется. Образовалась "дырка".
@ -109,10 +109,10 @@ alert(arr[1]); // undefined
var arr = ["Я", "изучаю", "JavaScript"];
*!*
arr.splice(1, 1); // начиная с позиции 1, удалить 1 элемент
arr.splice(1, 1); // начиная с позиции 1, удалить 1 элемент
*/!*
alert(arr); // осталось ["Я", "JavaScript"]
alert( arr ); // осталось ["Я", "JavaScript"]
```
Ниже продемонстрировано, как использовать `splice` для удаления одного элемента. Следующие за удаленным элементы сдвигаются, чтобы заполнить его место.
@ -122,7 +122,7 @@ alert(arr); // осталось ["Я", "JavaScript"]
var arr = ["Я", "изучаю", "JavaScript"];
*!*
arr.splice(0, 1); // удалить 1 элемент, начиная с позиции 0
arr.splice(0, 1); // удалить 1 элемент, начиная с позиции 0
*/!*
alert( arr[0] ); // "изучаю" стал первым элементом
@ -161,9 +161,9 @@ var arr = ["Я", "изучаю", "JavaScript"];
// с позиции 2
// удалить 0
// вставить "сложный", "язык"
arr.splice(2, 0, "сложный", "язык");
arr.splice(2, 0, "сложный", "язык");
alert(arr); // "Я", "изучаю", "сложный", "язык", "JavaScript"
alert( arr ); // "Я", "изучаю", "сложный", "язык", "JavaScript"
```
Допускается использование отрицательного номера позиции, которая в этом случае отсчитывается с конца:
@ -177,7 +177,7 @@ var arr = [1, 2, 5]
// затем вставить числа 3 и 4
arr.splice(-1, 0, 3, 4);
alert(arr); // результат: 1,2,3,4,5
alert( arr ); // результат: 1,2,3,4,5
```
## Метод slice
@ -190,9 +190,9 @@ alert(arr); // результат: 1,2,3,4,5
//+ run
var arr = ["Почему", "надо", "учить", "JavaScript"];
var arr2 = arr.slice(1,3); // элементы 1, 2 (не включая 3)
var arr2 = arr.slice(1, 3); // элементы 1, 2 (не включая 3)
alert(arr2); // надо, учить
alert( arr2 ); // надо, учить
```
Аргументы ведут себя так же, как и в строковом `slice`:
@ -301,7 +301,7 @@ arr.sort( compareNumeric*!*()*/!* ); // не сработает
```js
//+ run
[1, -2, 15, 2, 0, 8].sort(function(a, b) {
alert(a + " <> " + b);
alert( a + " <> " + b );
});
```
@ -326,10 +326,10 @@ function compareNumeric(a, b) {
```js
//+ run
var arr = [1,2,3];
var arr = [1, 2, 3];
arr.reverse();
alert(arr); // 3,2,1
alert( arr ); // 3,2,1
```
## concat
@ -340,12 +340,12 @@ alert(arr); // 3,2,1
```js
//+ run
var arr = [1,2];
var arr = [1, 2];
*!*
var newArr = arr.concat(3,4);
var newArr = arr.concat(3, 4);
*/!*
alert(newArr); // 1,2,3,4
alert( newArr ); // 1,2,3,4
```
У `concat` есть одна забавная особенность.
@ -356,13 +356,13 @@ alert(newArr); // 1,2,3,4
```js
//+ run
var arr = [1,2];
var arr = [1, 2];
*!*
var newArr = arr.concat( [3,4], 5);// то же самое, что arr.concat(3,4,5)
var newArr = arr.concat([3, 4], 5); // то же самое, что arr.concat(3,4,5)
*/!*
alert(newArr); // 1,2,3,4,5
alert( newArr ); // 1,2,3,4,5
```
## indexOf/lastIndexOf
@ -380,7 +380,7 @@ alert(newArr); // 1,2,3,4,5
```js
//+ run
var arr = [ 1, 0, false ];
var arr = [1, 0, false];
alert( arr.indexOf(0) ); // 1
alert( arr.indexOf(false) ); // 2
@ -401,13 +401,13 @@ alert( arr.indexOf(null) ); // -1
Например, организуем такую проверку для коллекции строк `"div"`, `"a"` и `"form"`:
```js
var store = { }; // объект для коллекции
var store = {}; // объект для коллекции
var items = ["div", "a", "form"];
for(var i=0; i<items.length; i++) {
for (var i = 0; i < items.length; i++) {
var key = items[i]; // для каждого элемента создаём свойство
store[ key ] = true; // значение здесь не важно
store[key] = true; // значение здесь не важно
}
```
@ -434,7 +434,7 @@ var user = {
var keys = Object.keys(user);
alert(keys); // name, age
alert( keys ); // name, age
```
## Итого

View file

@ -10,7 +10,7 @@ var arr = ["Есть", "жизнь", "на", "Марсе"];
*!*
var arrLength = [];
for(var i=0; i<arr.length; i++) {
for (var i = 0; i < arr.length; i++) {
arrLength[i] = arr[i].length;
}
*/!*

View file

@ -11,8 +11,9 @@
То есть:
```js
для arr = [1,2,3,4,5]
getSums(arr) = [1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4+5] = [1, 3, 6, 10, 15]
//+ no-beautify
для arr = [ 1, 2, 3, 4, 5 ]
getSums( arr ) = [ 1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4+5 ] = [ 1, 3, 6, 10, 15 ]
```
Еще пример: `getSums([-2,-1,0,1]) = [-2,-3,-3,-2]`.
@ -20,4 +21,4 @@ getSums(arr) = [1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4+5] = [1, 3, 6, 10, 15]
<ul>
<li>Функция не должна модифицировать входной массив.</li>
<li>В решении используйте метод `arr.reduce`.</li>
</ul>
</ul>

View file

@ -25,7 +25,7 @@
var arr = ["Яблоко", "Апельсин", "Груша"];
arr.forEach(function(item, i, arr) {
alert(i + ": " + item + " (массив:" + arr + ")");
alert( i + ": " + item + " (массив:" + arr + ")" );
});
```
@ -51,7 +51,7 @@ var positiveArr = arr.filter(function(number) {
});
*/!*
alert(positiveArr); // 1,2,3
alert( positiveArr ); // 1,2,3
```
## map
@ -73,7 +73,7 @@ var urls = pages.map(function(page) {
*/!*
// к каждой строке был прибавлен префикс
alert(urls); // http://site.com/a.html, http://site.com/b.html...
alert( urls ); // http://site.com/a.html, http://site.com/b.html...
```
## every/some
@ -132,9 +132,11 @@ var arr = [1, 2, 3, 4, 5]
// для каждого элемента массива запустить функцию,
// промежуточный результат передавать первым аргументом далее
var result = arr.reduce(function(sum, current) { return sum + current; }, 0);
var result = arr.reduce(function(sum, current) {
return sum + current;
}, 0);
alert(result); // 15
alert( result ); // 15
```
Разберём, что в нём происходит.
@ -203,9 +205,11 @@ alert(result); // 15
var arr = [1, 2, 3, 4, 5]
// убрали 0 в конце
var result = arr.reduce(function(sum, current) { return sum + current });
var result = arr.reduce(function(sum, current) {
return sum + current
});
alert(result); // 15
alert( result ); // 15
```
Результат -- точно такой же! Это потому, что при отсутствии `initialValue` в качестве первого значения берётся первый элемент массива, а перебор стартует со второго.