язык программирования
Some of my biggest regrets!
Brendan Eich
<script>
let name = "Roman";
</script>
<script>
console.log(name); // "Roman"
</script>
<script>
(function () {
let name = "Roman";
}());
</script>
Избегайте глобальных переменных.
<script type="module">
let name = "Roman";
</script>
<script>
Number();
window.Number();
</script>
Браузер
window
Node.js
global
Array Number
Boolean Object
Date RegExp
Function String
// массив заданного размера
let predefinedSize = new Array(31);
// выражение на основе переменных
let expr = new RegExp(`${prefix}`);
Однако, в большинстве случаев лучше использовать литерал, а не конструктор.
String(5); // '5'
Number('30'); // 30
Boolean([]); // true
Array.isArray([]);
String.fromCharCode('48');
Number.MAX_SAFE_INTEGER;
Используйте REPL, чтобы изучить свойства того или иного пространства имён.
Error SyntaxError
EvalError TypeError
RangeError URIError
ReferenceError
try {
JSON.parse('Invalid JSON');
} catch (err) {
if (err instanceof SyntaxError) {
// handle error
}
throw err;
}
decodeURI
decodeURIComponent
encodeURI
encodeURIComponent
Эти функции пригодятся, если вы будете самостоятельно формировать URL.
> encodeURI('Hello world')
"Hello%20world"
isFinite
isNaN
parseFloat
parseInt
Map
Set
WeakMap
WeakSet
ArrayBuffer Int8Array
DataView Uint16Array
Float32Array Uint32Array
Float64Array Uint8Array
Int16Array Uint8ClampedArray
Int32Array
console.log
console.error
console.time
console.timeEnd
> console.time('timer')
undefined
> console.timeEnd('timer')
timer: 6384.525ms
let greet = function (whom) {
return `Hello ${whom}`;
};
greet('world'); // Hello world
let count = function step(number) {
console.log(number);
if (number > 0) {
step(number - 1);
}
};
function greet(whom) {
return `Hello ${whom}`;
}
greet('world');
greet('world'); // Hello world
function greet(whom) {
return `Hello ${whom}`;
}
Всплытие характерно только для Function Declaration. Для Function Expression вызывать функцию можно только после объявления.
let greet = (whom) => {
return `Hello ${whom}`;
};
let greet = whom => `Hello ${whom}`;
let us = ['me', 'you']
us.map(whom => `Hello ${whom}`);
// ['Hello me', 'Hello you']
let createPerson = () => ({
name: 'Roman',
age: 28
});
Если стрелочная функция возвращает объект, фигурные скобки нужно обернуть в круглые.
function sum(a, b) { // parameters
return a + b;
}
sum(2, 3); // arguments
function sum(a, b) {
}
sum(1, 2); // undefined
function sum(a, b) {
return a + b;
}
sum(1); // NaN (1 + undefined)
function sum(a, b = 2) {
return a + b;
}
sum(1); // 3
function sum(a, b) {
if (b === undefined) {
b = 2;
}
return a + b;
}
sum(1); // 3
function sum(a, b) {
b = b || 2;
return a + b;
}
sum(1); // 3
function sum(a, b) {
b = b || 2;
return a + b;
}
sum(1, 0); // 3 😱
function sumAll(a, b, c, d, e, f) {
...
}
sumAll(1, 2, 3, 4, 5, 6, 7, 8, 9);
function sumAll(...numbers) {
let total = 0;
for (let number of numbers) {
total += number;
}
return total;
}
function sumAll() {
let total = 0;
for (let number of arguments) {
total += number;
}
return total;
}
Math.max(1, 2, 3, 4, 5); // 5
let numbers = [1, 2, 3, 4, 5];
Math.max(numbers); // NaN
let numbers = [1, 2, 3, 4, 5];
Math.max(...numbers);
let numbers = [1, 2, 3, 4, 5];
Math.max.apply(null, numbers);
let showButton =
function (round, animated) {
if (round) { ... }
if (animated) { ... }
};
showButton(true, false);
let showButton =
function (params) {
if (params.round) { ... }
if (params.animated) { ... }
};
showButton({ round: true,
animated: false });
let showButton =
function ({ round, animated }) {
if (round) { ... }
if (animated) { ... }
};
showButton({ round: true,
animated: false });
let showButton =
function ({ round = false
, animated = false }) {
...
};
showButton({ round: true });
let chars = [];
chars[0] = 'a';
chars[2] = 'c';
console.log(chars); // ['a', , 'c']
Такой массив называется разрежённым.
let chars = new Array(3);
console.log(chars); // [ , , ]
chars.fill(0);
console.log(chars); // [0, 0, 0]
Конструктор создаёт массив с дырками. Их нужно заполнить самостоятельно.
let chars = ['a', 'b', 'c'];
delete chars[2];
console.log(chars); // ['a', 'b', ]
console.log(chars.length); // 3
let chars = ['a', 'b', 'c'];
chars.splice(1, 2); // ['b', 'c']
console.log(chars); // ['a']
console.log(chars.length); // 1
> [ 'a', 'b' ].length
2
> [ 'a', , 'b' ].length
3
Свойство length
отслеживает наибольший индекс элемента массива, а не его размер.
let chars = ['a', 'b', 'c'];
chars.length = 5;
console.log(chars); // ['a', 'b', 'c', , ]
chars.length = 1;
console.log(chars); // ['a']
Destructive – изменяют исходный массив
Nondestructive – создают новый массив
shift pop splice
unshift push
Эти методы изменяют исходный массив.
reverse
sort
Эти методы изменяют исходный массив.
[1, 2, 10]
.sort(); // [1, 10, 2]
let asNumbers = (a, b) => {
if (a > b) return 1;
if (a < b) return -1;
return 0;
}
[1, 2, 10]
.sort(asNumbers); // [1, 2, 10]
['уж', 'ёж']
.sort(); // ['уж', 'ёж']
let asStrings = (a, b) => {
return a.localeCompare(b);
}
['уж', 'ёж']
.sort(asStrings); // ['ёж', 'уж']
concat
slice
join
let chars = ['a', 'b', 'c'];
chars.slice(0, 1); // ['a']
chars.slice(1, -1); // ['b']
chars.slice(-2); // ['b', 'c']
chars.slice(); // ['a', 'b', 'c']
slice удобно использовать перед вызовом мутирующего метода, чтобы не затрагивать исходный массив.
arr.<method>(callback);
function callback(value, index) {
...
}
Все рассматриваемые далее методы создают новый массив, а не изменяют исходный.
let fruits = ['apple', 'pear'];
fruits.forEach((elem, index) => {
console.log(elem, index);
});
let numbers = [1, 10, 2];
let result = numbers.some(x => {
return x > 5;
});
console.log(result); // true
some и every – ленивые методы. Они не будут обходить все элементы, если условие уже выполнено (или уже не выполнено).
let numbers = [1, -10, 2];
let positive = numbers.filter(x => {
return x > 0;
});
console.log(positive); // [1, 2]
console.log(numbers); // [1, -10, 2]
let numbers = [1, -10, 2];
numbers = numbers.filter((x, i) => {
return i !== 1;
});
console.log(numbers); // [1, 2]
let numbers = [1, undefined, 2];
numbers = numbers.filter(Boolean);
console.log(numbers); // [1, 2]
Данный подход не сработает для удаления дырок в массиве – filter, как и остальные методы из этой группы, пропускает дырки при обходе массива.
let numbers = [1, 2];
let doubles = numbers.map(x => {
return x * 2;
});
console.log(doubes); // [2, 4]
let xs = [1, 2, 3];
let sum = xs.reduce((prev, x) => {
return prev + x;
});
let numbers = [1, -1, 3, -3];
numbers
.filter(x => x > 0)
.map(x => x * 2)
.reduce((x, y) => x + y);
Если коллбэк становится слишком большим, его стоит вынести в переменную. Таким образом можно сохранять цепочку вызовов компактной и простой для понимания.
let set = new Set(['hello', 'world', 'hello']);
set.size; // 2
set.has('hello'); // true
let set = new Set();
set.add({ name: "Roman" });
set.add({ name: "Roman" });
set.size; // 2
Сравнение осуществляется эквивалентно оператору ===, за исключением NaN – он считается равным самому себе. Также считаются равными +0 и -0
let set = new Set(['hello', 'world', 'hello']);
let arr = [...set];
console.log(arr); // ['hello', 'world']
let map = new Map();
let key = {};
map.set(key, 'Hello');
map.get(key); // Hello
Строка в формате ISO 8601 Extended Format.
new Date('2017-10-17T19:48:21.684Z')
Не рекомендуется – результат зависит от реализации.
Node.js
> new Date('2017-10-17T00:00:00')
2017-10-17T00:00:00.000Z
Браузер
❯ new Date('2017-10-17T00:00:00')
2017-10-16T19:00:00.000Z
Количество миллисекунд с 1970-01-01.
new Date(timestamp)
> new Date(1508270783253)
2017-10-17T20:06:23.253Z
let currentTimestamp = Date.now();
new Date(currentTimestamp);
Создаёт объект для текущей даты и времени.
new Date()
> new Date()
2017-10-17T19:59:20.068Z
Создаёт объект с учётом временной зоны.
new Date(year, month, date?,
hours?, minutes?, seconds?,
milliseconds?
)
Месяц — в пределах от 0 (январь) до 11 (декабрь).
> new Date(2012, 10, 10)
2012-11-09T19:00:00.000Z
let ts = Date.UTC(2012, 10, 10);
let utcDate = new Date(ts);
> new Date(Date.UTC(2012, 10, 10))
2012-11-10T00:00:00.000Z
Локальное время
get<unit>
set<unit>
UTC
getUTC<unit>
setUTC<unit>
|
|
> let d = new Date(2010, 10, 10)
'Wed Nov 10 2010 00:00:00 GMT+0500'
> d.getMonth()
10
> d.setUTCHours(20)
1289332800000
getFullYear
> d.getYear()
110
> d.getFullYear()
2010
getYear
, setYear
, getUTCYear
, setUTCYear
– deprecated.
Для компьютеров
> d.toISOString()
'2010-11-09T20:00:00.000Z'
Для людей
> `${d.getHours()}:${d.getMinutes()}`
'1:40'
Timestamp.
new Date().getTime()
Смещение в минутах относительно UTC.
new Date().getTimezoneOffset()
If it's more than two inches,
rethink it. You probably want
to use a different tool.
Douglas Crockford
/^\d{2}:\d{2}:\d{2}$/
/^((?:(?:[^?+*{}()[\]\\|]+|\\.|\[(?:\^?\\.|\^[^\\]|[^\\^])(?:[^\]\\]+|\\.)*\]|\((?:\?[:=!]|\?<[=!]|\?>)?(?1)??\)|\(\?(?:R|[+-]?\d+)\))(?:(?:[?+*]|\{\d+(?:,\d*)?\})[?+]?)?|\|)*)$/
let name = 'Roman';
let regex =
new RegExp(`Hello ${name}`);
let str = 'Hello Roman!'
str.replace(regex, 'Hi Pyotr');
/\w/.test('ё'); // false
/[а-я]/.test('ё'); // false
/[а-яё]/.test('ё'); // true
'аа'.replace('а', 'A'); // 'Aa'
'аа'.replace(/а/g, 'A'); // 'AA'
g – глобальный флаг регулярного выражения