es6
This commit is contained in:
parent
43dfa400c1
commit
413e552c29
5 changed files with 188 additions and 112 deletions
|
@ -1,10 +1,5 @@
|
||||||
# ES-2015 сейчас
|
# ES-2015 сейчас
|
||||||
|
|
||||||
[smart header="Этот раздел -- в активной разработке"]
|
|
||||||
Стандарт ES-2015 недавно был принят окончательно, и этот раздел находится в ежедневной разработке.
|
|
||||||
|
|
||||||
[/smart]
|
|
||||||
|
|
||||||
[Стандарт ES-2015](http://www.ecma-international.org/publications/standards/Ecma-262.htm) был принят в июне 2015. Пока что большинство браузеров реализуют его частично, текущее состояние реализации различных возможностей можно посмотреть здесь: [](https://kangax.github.io/compat-table/es6/).
|
[Стандарт ES-2015](http://www.ecma-international.org/publications/standards/Ecma-262.htm) был принят в июне 2015. Пока что большинство браузеров реализуют его частично, текущее состояние реализации различных возможностей можно посмотреть здесь: [](https://kangax.github.io/compat-table/es6/).
|
||||||
|
|
||||||
Когда стандарт будет более-менее поддерживаться во всех браузерах, то весь учебник будет обновлён в соответствии с ним. Пока же, как центральное место для "сбора" современных фич JavaScript, создан этот раздел.
|
Когда стандарт будет более-менее поддерживаться во всех браузерах, то весь учебник будет обновлён в соответствии с ним. Пока же, как центральное место для "сбора" современных фич JavaScript, создан этот раздел.
|
||||||
|
@ -68,7 +63,7 @@
|
||||||
|
|
||||||
Это означает, что при запуске примеров в браузере, который их не поддерживает, будет ошибка. Это не означает, что пример неправильный! Просто пока нет поддержки...
|
Это означает, что при запуске примеров в браузере, который их не поддерживает, будет ошибка. Это не означает, что пример неправильный! Просто пока нет поддержки...
|
||||||
|
|
||||||
Рекомендуется [Chrome Canary](https://www.google.com/chrome/browser/canary.html), Edge или [Firefox Developer Edition](https://www.mozilla.org/en-US/firefox/channel/#developer).
|
Рекомендуется [Chrome Canary](https://www.google.com/chrome/browser/canary.html), Edge или [Firefox Developer Edition](https://www.mozilla.org/en-US/firefox/channel/#developer), большинство примеров в них работает.
|
||||||
|
|
||||||
Впрочем, если пример в браузере не работает (обычно проявляется как ошибка синтаксиса) -- почти все примеры вы можете запустить его при помощи Babel, на странице [Babel: try it out](https://babeljs.io/repl/). Там же увидите и преобразованный код.
|
Впрочем, если пример в браузере не работает (обычно проявляется как ошибка синтаксиса) -- почти все примеры вы можете запустить его при помощи Babel, на странице [Babel: try it out](https://babeljs.io/repl/). Там же увидите и преобразованный код.
|
||||||
|
|
||||||
|
@ -78,10 +73,3 @@
|
||||||
|
|
||||||
Итак, поехали!
|
Итак, поехали!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,12 @@ let a = 5;
|
||||||
|
|
||||||
## let
|
## let
|
||||||
|
|
||||||
У объявлений `let` три основных отличия от `var`:
|
У объявлений переменной через `let` есть три основных отличия от `var`:
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li>**Область видимости переменной `let` -- блок `{...}`.**
|
<li>**Область видимости переменной `let` -- блок `{...}`.**
|
||||||
|
|
||||||
Как мы помним, переменная, объявленная через `var`, видна везде в функции. В старом стандарте минимальная "область видимости" -- функция.
|
Как мы помним, переменная, объявленная через `var`, видна везде в функции.
|
||||||
|
|
||||||
Переменная, объявленная через `let`, видна только в рамках блока `{...}`, в котором объявлена.
|
Переменная, объявленная через `let`, видна только в рамках блока `{...}`, в котором объявлена.
|
||||||
|
|
||||||
|
@ -37,7 +37,9 @@ if (true) {
|
||||||
alert(apples); // 10 (снаружи блока то же самое)
|
alert(apples); // 10 (снаружи блока то же самое)
|
||||||
```
|
```
|
||||||
|
|
||||||
То же самое с `let`:
|
В примере выше `apples` -- одна переменная на весь код, которая модифицируется в `if`.
|
||||||
|
|
||||||
|
То же самое с `let` будет работать по-другому:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
|
@ -58,7 +60,25 @@ alert(apples); // 5 (снаружи блока значение не измен
|
||||||
|
|
||||||
Здесь, фактически, две независимые переменные `apples`, одна -- глобальная, вторая -- в блоке `if`.
|
Здесь, фактически, две независимые переменные `apples`, одна -- глобальная, вторая -- в блоке `if`.
|
||||||
|
|
||||||
Заметим, что если объявление `apples` в строке `(*)` закомментировать, то в последнем `alert` будет ошибка: переменная неопределена. Это потому что переменная `let` всегда видна именно в том блоке, где объявлена и не более.
|
Заметим, что если объявление `let apples` в первой строке `(*)` удалить, то в последнем `alert` будет ошибка: переменная неопределена:
|
||||||
|
|
||||||
|
```js
|
||||||
|
//+ run
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
let apples = 10;
|
||||||
|
|
||||||
|
alert(apples); // 10 (внутри блока)
|
||||||
|
}
|
||||||
|
|
||||||
|
*!*
|
||||||
|
alert(apples); // ошибка!
|
||||||
|
*/!*
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Это потому что переменная `let` всегда видна именно в том блоке, где объявлена, и не более.
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<li>**Переменная `let` видна только после объявления.**
|
<li>**Переменная `let` видна только после объявления.**
|
||||||
|
@ -98,17 +118,16 @@ let x;
|
||||||
let x; // ошибка: переменная x уже объявлена
|
let x; // ошибка: переменная x уже объявлена
|
||||||
```
|
```
|
||||||
|
|
||||||
Это -- хоть и выглядит ограничением по сравнению с `var`, но на самом деле проблем не создаёт, так как область видимости ограничена блоком.
|
Это -- хоть и выглядит ограничением по сравнению с `var`, но на самом деле проблем не создаёт. Например, два таких цикла совсем не конфликтуют:
|
||||||
|
|
||||||
Например, два таких цикла совсем не конфликтуют:
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// каждый цикл имеет свою переменную i
|
||||||
for(let i = 0; i<10; i++) { /* … */ }
|
for(let i = 0; i<10; i++) { /* … */ }
|
||||||
for(let i = 0; i<10; i++) { /* … */ }
|
for(let i = 0; i<10; i++) { /* … */ }
|
||||||
|
|
||||||
alert( i ); // ошибка, переменная не определена
|
alert( i ); // ошибка: глобальной i нет
|
||||||
```
|
```
|
||||||
|
|
||||||
При объявлении внутри цикла переменная `i` будет видна только в блоке цикла. Она не видна снаружи, поэтому будет ошибка в последнем `alert`.
|
При объявлении внутри цикла переменная `i` будет видна только в блоке цикла. Она не видна снаружи, поэтому будет ошибка в последнем `alert`.
|
||||||
|
@ -117,7 +136,7 @@ alert( i ); // ошибка, переменная не определена
|
||||||
</li>
|
</li>
|
||||||
<li>**При использовании в цикле, для каждой итерации создаётся своя переменная.**
|
<li>**При использовании в цикле, для каждой итерации создаётся своя переменная.**
|
||||||
|
|
||||||
Переменная `var` -- одна на все итерации цикла (и видна после цикла):
|
Переменная `var` -- одна на все итерации цикла и видна даже после цикла:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
|
@ -126,9 +145,9 @@ for(var i=0; i<10; i++) { /* … */ }
|
||||||
alert(i); // 10
|
alert(i); // 10
|
||||||
```
|
```
|
||||||
|
|
||||||
С переменной `let` -- всё по-другому. Добавляется ещё одна область видимости: блок цикла.
|
С переменной `let` -- всё по-другому.
|
||||||
|
|
||||||
Каждому блоку цикла соответствует своя, независимая, переменная `let`. Если внутри цикла объявляются функции, то в замыкании каждой будет та переменная, которая была при итерации.
|
Каждому повторению цикла соответствует своя независимая переменная `let`. Если внутри цикла есть вложенные объявления функций, то в замыкании каждой будет та переменная, которая была при соответствующей итерации.
|
||||||
|
|
||||||
Это позволяет легко решить классическую проблему с замыканиями, описанную в задаче [](/task/make-army).
|
Это позволяет легко решить классическую проблему с замыканиями, описанную в задаче [](/task/make-army).
|
||||||
|
|
||||||
|
@ -183,7 +202,7 @@ apple = 10; // ошибка
|
||||||
<ul>
|
<ul>
|
||||||
<li>Видны только после объявления и только в текущем блоке.</li>
|
<li>Видны только после объявления и только в текущем блоке.</li>
|
||||||
<li>Нельзя переобъявлять (в том же блоке).</li>
|
<li>Нельзя переобъявлять (в том же блоке).</li>
|
||||||
<li>В цикле каждое значение `let` принадлежит конкретной итерации цикла (и видно в замыканиях).</li>
|
<li>При объявлении переменной в цикле `for(let …)` -- она видна только в этом цикле. Причём каждой итерации соответствует своя переменная `let`.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
Переменная `const` -- это константа, в остальном -- как `let`.
|
Переменная `const` -- это константа, в остальном -- как `let`.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
# Деструктуризация
|
# Деструктуризация
|
||||||
|
|
||||||
*Деструктуризация* (destructuring assignment) -- способ присвоить массив или объект сразу нескольким переменным.
|
*Деструктуризация* (destructuring assignment) -- это особый синтаксис присваивания, при котором можно присвоить массив или объект сразу нескольким переменным, разбив его на части.
|
||||||
|
|
||||||
## Массив
|
## Массив
|
||||||
|
|
||||||
|
@ -10,15 +10,33 @@
|
||||||
```js
|
```js
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let [firstName, lastName] = "Илья Кантор".split(" ");
|
let [firstName, lastName] = ["Илья", "Кантор"];
|
||||||
|
|
||||||
alert(firstName); // Илья
|
alert(firstName); // Илья
|
||||||
alert(lastName); // Кантор
|
alert(lastName); // Кантор
|
||||||
```
|
```
|
||||||
|
|
||||||
При таком присвоении первые два значения массива будут помещены в переменные, а последующие -- будут отброшены.
|
При таком присвоении первое значение массива пойдёт в переменную `firstName`, второе -- в `lastName`, а последующие (если есть) -- будут отброшены.
|
||||||
|
|
||||||
Однако, можно добавить ещё один параметр, который получит "всё остальное", при помощи троеточия ("spread"):
|
Ненужные элементы массива также можно отбросить, поставив лишнюю запятую:
|
||||||
|
|
||||||
|
```js
|
||||||
|
//+ run
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
*!*
|
||||||
|
// первый и второй элементы не нужны
|
||||||
|
let [, , title] = "Юлий Цезарь Император Рима".split(" ");
|
||||||
|
*/!*
|
||||||
|
|
||||||
|
alert(title); // Император
|
||||||
|
```
|
||||||
|
|
||||||
|
В коде выше первый и второй элементы массива никуда не записались, они были отброшены. Как, впрочем, и все элементы после третьего.
|
||||||
|
|
||||||
|
### Оператор "spread"
|
||||||
|
|
||||||
|
Если мы хотим получить и последующие значения массива, но не уверены в их числе -- можно добавить ещё один параметр, который получит "всё остальное", при помощи оператора `"..."` ("spread", троеточие):
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
|
@ -33,17 +51,32 @@ alert(lastName); // Цезарь
|
||||||
alert(rest); // Император,Рима (массив из 2х элементов)
|
alert(rest); // Император,Рима (массив из 2х элементов)
|
||||||
```
|
```
|
||||||
|
|
||||||
Значением `rest` будет массив из оставшихся элементов массива.
|
Значением `rest` будет массив из оставшихся элементов массива. Вместо `rest` можно использовать и другое имя переменной, оператор здесь -- троеточие. Оно должно стоять только последним элементом в списке слева.
|
||||||
|
|
||||||
**Можно задать и значения по умолчанию, если массив почему-то оказался короче, чем ожидалось.**
|
### Значения по умолчанию
|
||||||
|
|
||||||
|
Если значений в массиве меньше, чем переменных -- ошибки не будет, просто присвоится `undefined`:
|
||||||
|
|
||||||
Они задаются через знак `=`, например:
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
|
let [firstName, lastName] = [];
|
||||||
|
*/!*
|
||||||
|
|
||||||
|
alert(firstName); // undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
Впрочем, как правило, в таких случаях задают значение по умолчанию. Для этого нужно после переменной использовать символ `=` со значением, например:
|
||||||
|
|
||||||
|
```js
|
||||||
|
//+ run
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
*!*
|
||||||
|
// значения по умолчанию
|
||||||
let [firstName="Гость", lastName="Анонимный"] = [];
|
let [firstName="Гость", lastName="Анонимный"] = [];
|
||||||
*/!*
|
*/!*
|
||||||
|
|
||||||
|
@ -51,7 +84,7 @@ alert(firstName); // Гость
|
||||||
alert(lastName); // Анонимный
|
alert(lastName); // Анонимный
|
||||||
```
|
```
|
||||||
|
|
||||||
В качестве значений по умолчанию можно использовать не только примитивы, но и выражения, содержащие вызовы функций:
|
В качестве значений по умолчанию можно использовать не только примитивы, но и выражения, даже включающие в себя вызовы функций:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
|
@ -70,27 +103,18 @@ alert(firstName); // Вася
|
||||||
alert(lastName); // 1436...-visitor
|
alert(lastName); // 1436...-visitor
|
||||||
```
|
```
|
||||||
|
|
||||||
Заметим, что вызов функции `defaultLastName` будет осуществлён только при необходимости, то есть если значения нет в массиве.
|
Заметим, что вызов функции `defaultLastName()` для генерации значения по умолчанию будет осуществлён только при необходимости, то есть если значения нет в массиве.
|
||||||
|
|
||||||
**Ненужные элементы массива можно отбросить, поставив лишнюю запятую:**
|
|
||||||
|
|
||||||
```js
|
|
||||||
//+ run
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
*!*
|
|
||||||
// первый и второй элементы не нужны
|
|
||||||
let [, , title] = "Юлий Цезарь Император Рима".split(" ");
|
|
||||||
*/!*
|
|
||||||
|
|
||||||
alert(title); // Император
|
|
||||||
```
|
|
||||||
|
|
||||||
В коде выше первый и второй элементы массива никуда не записались, они были отброшены. Как, впрочем, и все элементы после третьего.
|
|
||||||
|
|
||||||
## Деструктуризация объекта
|
## Деструктуризация объекта
|
||||||
|
|
||||||
Деструктуризация может "мгновенно" разобрать объект по переменным.
|
Деструктуризацию можно использовать и с объектами. При этом мы указываем, какие свойства в какие переменные должны "идти".
|
||||||
|
|
||||||
|
Базовый синтаксис:
|
||||||
|
```js
|
||||||
|
let {var1, var2} = {var1:…, var2…}
|
||||||
|
```
|
||||||
|
|
||||||
|
Объект справа -- уже существующий, который мы хотим разбить на переменные. А слева -- список переменных, в которые нужно соответствующие свойства записать.
|
||||||
|
|
||||||
Например:
|
Например:
|
||||||
|
|
||||||
|
@ -98,35 +122,35 @@ alert(title); // Император
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let menuOptions = {
|
let options = {
|
||||||
title: "Меню",
|
title: "Меню",
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 200
|
height: 200
|
||||||
};
|
};
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
let {title, width, height} = menuOptions;
|
let {title, width, height} = options;
|
||||||
*/!*
|
*/!*
|
||||||
|
|
||||||
alert(`${title} ${width} ${height}`); // Меню 100 200
|
alert(`${title} ${width} ${height}`); // Меню 100 200
|
||||||
```
|
```
|
||||||
|
|
||||||
Как видно, свойства автоматически присваиваются соответствующим переменным.
|
Как видно, свойства `options.title`, `options.width` и `options.height` автоматически присвоились соответствующим переменным.
|
||||||
|
|
||||||
Если хочется присвоить свойство объекта в переменную с другим именем, можно указать соответствие через двоеточие, вот так:
|
Если хочется присвоить свойство объекта в переменную с другим именем, например, чтобы свойство `options.width` пошло в переменную `w`, то можно указать соответствие через двоеточие, вот так:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let menuOptions = {
|
let options = {
|
||||||
title: "Меню",
|
title: "Меню",
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 200
|
height: 200
|
||||||
};
|
};
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
let {width: w, height: h, title} = menuOptions;
|
let {width: w, height: h, title} = options;
|
||||||
*/!*
|
*/!*
|
||||||
|
|
||||||
alert(`${title} ${w} ${h}`); // Меню 100 200
|
alert(`${title} ${w} ${h}`); // Меню 100 200
|
||||||
|
@ -140,12 +164,12 @@ alert(`${title} ${w} ${h}`); // Меню 100 200
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let menuOptions = {
|
let options = {
|
||||||
title: "Меню"
|
title: "Меню"
|
||||||
};
|
};
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
let {width=100, height=200, title} = menuOptions;
|
let {width=100, height=200, title} = options;
|
||||||
*/!*
|
*/!*
|
||||||
|
|
||||||
alert(`${title} ${width} ${height}`); // Меню 100 200
|
alert(`${title} ${width} ${height}`); // Меню 100 200
|
||||||
|
@ -158,33 +182,33 @@ alert(`${title} ${width} ${height}`); // Меню 100 200
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let menuOptions = {
|
let options = {
|
||||||
title: "Меню"
|
title: "Меню"
|
||||||
};
|
};
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
let {width:w=100, height:h=200, title} = menuOptions;
|
let {width:w=100, height:h=200, title} = options;
|
||||||
*/!*
|
*/!*
|
||||||
|
|
||||||
alert(`${title} ${w} ${h}`); // Меню 100 200
|
alert(`${title} ${w} ${h}`); // Меню 100 200
|
||||||
```
|
```
|
||||||
|
|
||||||
А что, если в объекте больше значений, чем переменных? Можно ли куда-то присвоить "остаток"?
|
А что, если в объекте больше значений, чем переменных? Можно ли куда-то присвоить "остаток", аналогично массивам?
|
||||||
|
|
||||||
Такой возможности в текущем стандарте нет. Она планируется в будущем стандарте, и выглядеть она будет аналогично массивам:
|
Такой возможности в текущем стандарте нет. Она планируется в будущем стандарте, и выглядеть она будет примерно так:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let menuOptions = {
|
let options = {
|
||||||
title: "Меню",
|
title: "Меню",
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 200
|
height: 200
|
||||||
};
|
};
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
let {title, ...size} = menuOptions;
|
let {title, ...size} = options;
|
||||||
*/!*
|
*/!*
|
||||||
|
|
||||||
// title = "Меню"
|
// title = "Меню"
|
||||||
|
@ -195,22 +219,25 @@ let {title, ...size} = menuOptions;
|
||||||
|
|
||||||
[smart header="Деструктуризация без объявления"]
|
[smart header="Деструктуризация без объявления"]
|
||||||
|
|
||||||
В примерах выше переменные объявлялись прямо перед присваиванием. Конечно, можно использовать и уже существующие переменные.
|
В примерах выше переменные объявлялись прямо перед присваиванием: `let {…} = {…}`. Конечно, можно и без `let`, использовать уже существующие переменные.
|
||||||
|
|
||||||
Однако, для объектов есть небольшой "подвох". В JavaScript, если в основном потоке кода (не внутри другого выражения) встречается `{...}`, то это воспринимается как блок.
|
Однако, здесь есть небольшой "подвох". В JavaScript, если в основном потоке кода (не внутри другого выражения) встречается `{...}`, то это воспринимается как блок.
|
||||||
|
|
||||||
Например, можно использовать для ограничения видимости переменных:
|
Например, можно использовать такой блок для ограничения видимости переменных:
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
{
|
{
|
||||||
|
// вспомогательные переменные, локальные для блока
|
||||||
let a = 5;
|
let a = 5;
|
||||||
|
// поработали с ними
|
||||||
alert(a); // 5
|
alert(a); // 5
|
||||||
|
// больше эти переменные не нужны
|
||||||
}
|
}
|
||||||
alert(a); // ошибка нет такой переменной
|
alert(a); // ошибка нет такой переменной
|
||||||
```
|
```
|
||||||
|
|
||||||
...Но в данном случае это создаст проблему при деструктуризации:
|
Конечно, это бывает удобно, но в данном случае это создаст проблему при деструктуризации:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
let a, b;
|
let a, b;
|
||||||
|
@ -227,15 +254,17 @@ let a, b;
|
||||||
|
|
||||||
## Вложенные деструктуризации
|
## Вложенные деструктуризации
|
||||||
|
|
||||||
|
Если объект или массив содержат другие объекты или массивы, и их тоже хочется разбить на переменные -- не проблема.
|
||||||
|
|
||||||
Деструктуризации можно как угодно сочетать и вкладывать друг в друга.
|
Деструктуризации можно как угодно сочетать и вкладывать друг в друга.
|
||||||
|
|
||||||
Пример с подобъектом и подмассивом:
|
В коде ниже `options` содержит подобъект и подмассив. В деструктуризации ниже сохраняется та же структура:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let menuOptions = {
|
let options = {
|
||||||
size: {
|
size: {
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 200
|
height: 200
|
||||||
|
@ -243,16 +272,14 @@ let menuOptions = {
|
||||||
items: ["Пончик", "Пирожное"]
|
items: ["Пончик", "Пирожное"]
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let { title="Меню", size: {width, height}, items: [item1, item2] } = options;
|
||||||
title="Меню",
|
|
||||||
size: {width, height},
|
|
||||||
items: [item1, item2]
|
|
||||||
} = menuOptions;
|
|
||||||
|
|
||||||
// Меню 100 200 Пончик Пирожное
|
// Меню 100 200 Пончик Пирожное
|
||||||
alert(`${title} ${width} ${height} ${item1} ${item2}`);
|
alert(`${title} ${width} ${height} ${item1} ${item2}`);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Как видно, весь объект `options` корректно разбит на переменные.
|
||||||
|
|
||||||
|
|
||||||
## Итого
|
## Итого
|
||||||
|
|
||||||
|
@ -261,14 +288,19 @@ alert(`${title} ${width} ${height} ${item1} ${item2}`);
|
||||||
<li>Синтаксис:
|
<li>Синтаксис:
|
||||||
```js
|
```js
|
||||||
let {prop : varName = default, ...} = object
|
let {prop : varName = default, ...} = object
|
||||||
let [var1=default, var2, ...rest] = array
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Здесь двоеточие `:` задаёт отображение свойства в переменную, а `=` задаёт выражение, которое будет использовано, если значение отсутствует (не указано или `undefined`).
|
Здесь двоеточие `:` задаёт отображение свойства `prop` в переменную `varName`, а равенство `=default` задаёт выражение, которое будет использовано, если значение отсутствует (не указано или `undefined`).
|
||||||
|
|
||||||
|
Для массивов имеет значение порядок, поэтому нельзя использовать `:`, но значение по умолчанию -- можно:
|
||||||
|
|
||||||
|
```js
|
||||||
|
let [var1 = default, var2, ...rest] = array
|
||||||
|
```
|
||||||
|
|
||||||
Объявление переменной в начале конструкции не обязательно. Можно использовать и существующие переменные. Однако при деструктуризации объекта может потребоваться обернуть выражение в скобки.
|
Объявление переменной в начале конструкции не обязательно. Можно использовать и существующие переменные. Однако при деструктуризации объекта может потребоваться обернуть выражение в скобки.
|
||||||
</li>
|
</li>
|
||||||
<li>Вложенные объекты и массивы тоже работают, деструктуризации можно вкладывать друг в друга, сохраняя ту же структуру, что и исходный объект/массив.</li>
|
<li>Вложенные объекты и массивы тоже работают, при деструктуризации нужно лишь сохранить ту же структуру, что и исходный объект/массив.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
Как мы увидим далее, деструктуризации особенно пригодятся удобны при чтении объектных параметров функций.
|
Как мы увидим далее, деструктуризации особенно пригодятся удобны при чтении объектных параметров функций.
|
||||||
|
|
|
@ -84,7 +84,7 @@ function f(arg1, ...rest, arg2) { // arg2 после ...rest ?!
|
||||||
[/warn]
|
[/warn]
|
||||||
|
|
||||||
|
|
||||||
Выше мы увидели использование `...` для чтения параметров внутри функции. Но этот же оператор можно использовать и для передачи массива параметров как списка, например:
|
Выше мы увидели использование `...` для чтения параметров в объявлении функции. Но этот же оператор можно использовать и при вызове функции, для передачи массива параметров как списка, например:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
|
@ -92,19 +92,22 @@ function f(arg1, ...rest, arg2) { // arg2 после ...rest ?!
|
||||||
|
|
||||||
let numbers = [2, 3, 15];
|
let numbers = [2, 3, 15];
|
||||||
|
|
||||||
// Передаст массив как список аргументов: Math.max(2, 3, 15)
|
// Оператор ... в вызове передаст массив как список аргументов
|
||||||
|
// Этот вызов аналогичен Math.max(2, 3, 15)
|
||||||
let max = Math.max(*!*...numbers*/!*);
|
let max = Math.max(*!*...numbers*/!*);
|
||||||
|
|
||||||
alert( max ); // 15
|
alert( max ); // 15
|
||||||
```
|
```
|
||||||
|
|
||||||
Эти два вызова делают одно и то же:
|
Формально говоря, эти два вызова делают одно и то же:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
Math.max(...numbers);
|
Math.max(...numbers);
|
||||||
Math.max.apply(Math, numbers);
|
Math.max.apply(Math, numbers);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Похоже, что первый -- короче и красивее.
|
||||||
|
|
||||||
## Деструктуризация в параметрах
|
## Деструктуризация в параметрах
|
||||||
|
|
||||||
Если функция получает объект, то она может его тут же разбить в переменные:
|
Если функция получает объект, то она может его тут же разбить в переменные:
|
||||||
|
@ -113,7 +116,7 @@ Math.max.apply(Math, numbers);
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let menuOptions = {
|
let options = {
|
||||||
title: "Меню",
|
title: "Меню",
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 200
|
height: 200
|
||||||
|
@ -125,7 +128,7 @@ function showMenu({title, width, height}) {
|
||||||
alert(`${title} ${width} ${height}`); // Меню 100 200
|
alert(`${title} ${width} ${height}`); // Меню 100 200
|
||||||
}
|
}
|
||||||
|
|
||||||
showMenu(menuOptions);
|
showMenu(options);
|
||||||
```
|
```
|
||||||
|
|
||||||
Можно использовать и более сложную деструктуризацию, с соответствиями и значениями по умолчанию:
|
Можно использовать и более сложную деструктуризацию, с соответствиями и значениями по умолчанию:
|
||||||
|
@ -134,21 +137,36 @@ showMenu(menuOptions);
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let menuOptions = {
|
let options = {
|
||||||
title: "Меню"
|
title: "Меню"
|
||||||
};
|
};
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
function showMenu({title="Заголовок", width:w=100, height:h=200} = {}) {
|
function showMenu({title="Заголовок", width:w=100, height:h=200}) {
|
||||||
*/!*
|
*/!*
|
||||||
alert(`${title} ${w} ${h}`);
|
alert(`${title} ${w} ${h}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
showMenu(menuOptions); // Меню 100 200
|
// объект options будет разбит на переменные
|
||||||
|
showMenu(options); // Меню 100 200
|
||||||
|
```
|
||||||
|
|
||||||
|
Заметим, что в примере выше какой-то аргумент у `showMenu()` обязательно должен быть, чтобы разбить его на переменные.
|
||||||
|
|
||||||
|
Если хочется, чтобы функция могла быть вызвана вообще без аргументов -- нужно добавить ей параметр по умолчанию -- уже не внутрь деструктуризации, а в самом списке аргументов:
|
||||||
|
|
||||||
|
```js
|
||||||
|
//+ run
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function showMenu({title="Заголовок", width:w=100, height:h=200} *!*= {}*/!*) {
|
||||||
|
alert(`${title} ${w} ${h}`);
|
||||||
|
}
|
||||||
|
|
||||||
showMenu(); // Заголовок 100 200
|
showMenu(); // Заголовок 100 200
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Имя "name"
|
## Имя "name"
|
||||||
|
|
||||||
В свойстве `name` у функции находится её имя.
|
В свойстве `name` у функции находится её имя.
|
||||||
|
@ -166,19 +184,23 @@ let g = function g() {}; // g.name == "g"
|
||||||
alert(`${f.name} ${g.name}`) // f g
|
alert(`${f.name} ${g.name}`) // f g
|
||||||
```
|
```
|
||||||
|
|
||||||
В примере выше показаны Function Declaration и Named Function Expression.
|
В примере выше показаны Function Declaration и Named Function Expression. В синтаксисе выше довольно очевидно, что у этих функций есть имя `name`. В конце концов, оно указано в объявлении.
|
||||||
|
|
||||||
Но современный JavaScript идёт дальше, он старается даже анонимным функциям дать разумные имена.
|
Но современный JavaScript идёт дальше, он старается даже анонимным функциям дать разумные имена.
|
||||||
|
|
||||||
Например, при создании анонимной функции с одновременной записью в переменную или свойство -- её имя равно названию переменной (или свойства):
|
Например, при создании анонимной функции с одновременной записью в переменную или свойство -- её имя равно названию переменной (или свойства).
|
||||||
|
|
||||||
|
Например:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let g = function() {}; // g.name == "g"
|
// свойство g.name = "g"
|
||||||
|
let g = function() {};
|
||||||
|
|
||||||
let user = {
|
let user = {
|
||||||
sayHi: function() { }; // user.sayHi.name == "sayHi"
|
// свойство user.sayHi.name == "sayHi"
|
||||||
|
sayHi: function() { };
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -204,7 +226,7 @@ if (true) {
|
||||||
sayHi(); // ошибка, функции не существует
|
sayHi(); // ошибка, функции не существует
|
||||||
```
|
```
|
||||||
|
|
||||||
То есть, иными словами, такое объявление -- ведёт себя так же как `let sayHi = function ...`, сделанное в начале блока.
|
То есть, иными словами, такое объявление -- ведёт себя в точности как если бы `let sayHi = function() {…}` было сделано в начале блока.
|
||||||
|
|
||||||
## Функции через =>
|
## Функции через =>
|
||||||
|
|
||||||
|
@ -222,8 +244,6 @@ let inc = x => x+1;
|
||||||
alert( inc(1) ); // 2
|
alert( inc(1) ); // 2
|
||||||
```
|
```
|
||||||
|
|
||||||
То есть, слева от `=>` находится аргумент, а справа -- выражение, которое нужно вернуть.
|
|
||||||
|
|
||||||
Эти две записи -- примерно аналогичны:
|
Эти две записи -- примерно аналогичны:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
@ -232,7 +252,9 @@ let inc = x => x+1;
|
||||||
let inc = function(x) { return x + 1; };
|
let inc = function(x) { return x + 1; };
|
||||||
```
|
```
|
||||||
|
|
||||||
Если аргументов несколько, то они оборачиваются в скобки, например:
|
Как видно, `"x => x+1"` -- это уже готовая функция. Слева от `=>` находится аргумент, а справа -- выражение, которое нужно вернуть.
|
||||||
|
|
||||||
|
Если аргументов несколько, то нужно обернуть их в скобки, вот так:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
|
@ -242,16 +264,20 @@ let inc = function(x) { return x + 1; };
|
||||||
let sum = (a,b) => a + b;
|
let sum = (a,b) => a + b;
|
||||||
*/!*
|
*/!*
|
||||||
|
|
||||||
|
// аналог с function
|
||||||
|
// let inc = function(a, b) { return a + b; };
|
||||||
|
|
||||||
alert( sum(1, 2) ); // 3
|
alert( sum(1, 2) ); // 3
|
||||||
```
|
```
|
||||||
|
|
||||||
...А если совсем нет аргументов, но функцию хочется задать, то используются пустые скобки:
|
Если нужно задать функцию без аргументов, то также используются скобки, в этом случае -- пустые:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
|
// вызов getTime() будет возвращать текущее время
|
||||||
let getTime = () => `${new Date().getHours()} : ${new Date().getMinutes()}`;
|
let getTime = () => `${new Date().getHours()} : ${new Date().getMinutes()}`;
|
||||||
*/!*
|
*/!*
|
||||||
|
|
||||||
|
@ -277,7 +303,7 @@ let getTime = () => {
|
||||||
alert( getTime() ); // текущее время
|
alert( getTime() ); // текущее время
|
||||||
```
|
```
|
||||||
|
|
||||||
Заметим, что как только тело функции оборачивается в `{…}`, то оно уже автоматически перестаёт быть выражением. Такая функция должна делать явный `return`, как в примере выше, если конечно хочет что-либо возвратить.
|
Заметим, что как только тело функции оборачивается в `{…}`, то её результат уже не возвращается автоматически. Такая функция должна делать явный `return`, как в примере выше, если конечно хочет что-либо возвратить.
|
||||||
|
|
||||||
Функции-стрелки очень удобны в качестве коллбеков, например:
|
Функции-стрелки очень удобны в качестве коллбеков, например:
|
||||||
|
|
||||||
|
@ -294,7 +320,7 @@ let sorted = arr.sort( (a,b) => a - b );
|
||||||
alert(sorted); // 3, 5, 8
|
alert(sorted); // 3, 5, 8
|
||||||
```
|
```
|
||||||
|
|
||||||
Такая запись -- коротка и понятна.
|
Такая запись -- коротка и понятна. Далее мы познакомимся с дополнительными преимуществами использования функций-стрелок для этой цели.
|
||||||
|
|
||||||
## Функции-стрелки не имеют своего this
|
## Функции-стрелки не имеют своего this
|
||||||
|
|
||||||
|
@ -325,7 +351,7 @@ group.showList();
|
||||||
// Наш курс: Даша
|
// Наш курс: Даша
|
||||||
```
|
```
|
||||||
|
|
||||||
Здесь в `forEach` была использована функция-стрелка, поэтому `this.title` внутри -- тот же, что и во внешней функции `showList`. То есть, в данном случае -- `group.title`.
|
Здесь в `forEach` была использована функция-стрелка, поэтому `this.title` в коллбэке -- тот же, что и во внешней функции `showList`. То есть, в данном случае -- `group.title`.
|
||||||
|
|
||||||
Если бы в `forEach` вместо функции-стрелки была обычная функция, то была бы ошибка:
|
Если бы в `forEach` вместо функции-стрелки была обычная функция, то была бы ошибка:
|
||||||
|
|
||||||
|
@ -352,7 +378,7 @@ group.showList();
|
||||||
При запуске будет "попытка прочитать свойство `title` у `undefined`", так как `.forEach(f)` при запуске `f` не ставит `this`. То есть, `this` внутри `forEach` будет `undefined`.
|
При запуске будет "попытка прочитать свойство `title` у `undefined`", так как `.forEach(f)` при запуске `f` не ставит `this`. То есть, `this` внутри `forEach` будет `undefined`.
|
||||||
|
|
||||||
[warn header="Функции стрелки нельзя запускать с `new`"]
|
[warn header="Функции стрелки нельзя запускать с `new`"]
|
||||||
Отсутствие у функции-стрелки "своего `this`" влечёт за собой естественное ограничение: такие функции нельзя использовать в качестве конструктора, то есть вызывать через `new`.
|
Отсутствие у функции-стрелки "своего `this`" влечёт за собой естественное ограничение: такие функции нельзя использовать в качестве конструктора, то есть нельзя вызывать через `new`.
|
||||||
[/warn]
|
[/warn]
|
||||||
|
|
||||||
## Функции-стрелки не имеют своего arguments
|
## Функции-стрелки не имеют своего arguments
|
||||||
|
@ -404,8 +430,10 @@ sayHiDeferred("Вася"); // Привет, Вася! через 2 секунд
|
||||||
```js
|
```js
|
||||||
function defer(f, ms) {
|
function defer(f, ms) {
|
||||||
return function() {
|
return function() {
|
||||||
|
*!*
|
||||||
let args = arguments;
|
let args = arguments;
|
||||||
let ctx = this;
|
let ctx = this;
|
||||||
|
*/!*
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
return f.apply(ctx, args);
|
return f.apply(ctx, args);
|
||||||
}, ms);
|
}, ms);
|
||||||
|
@ -413,6 +441,8 @@ function defer(f, ms) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
В этом коде пришлось создавать дополнительные переменные `args` и `ctx` для передачи внешних аргументов и контекста через замыкание.
|
||||||
|
|
||||||
|
|
||||||
## Итого
|
## Итого
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
let str = `обратные кавычки`;
|
let str = `обратные кавычки`;
|
||||||
```
|
```
|
||||||
|
|
||||||
Основные отличия от `"…"` и `'…'`:
|
Основные отличия от двойных `"…"` и одинарных `'…'` кавычек:
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>**В них разрешён перевод строки.**
|
<li>**В них разрешён перевод строки.**
|
||||||
|
@ -38,7 +38,7 @@ let oranges = 3;
|
||||||
alert(`${apples} + ${oranges} = ${apples + oranges}`); // 2 + 3 = 5
|
alert(`${apples} + ${oranges} = ${apples + oranges}`); // 2 + 3 = 5
|
||||||
```
|
```
|
||||||
|
|
||||||
Как видно, можно вставлять как и значение переменной, так и более сложные выражения, вызовы функций и т.п. Это называют "интерполяцией".
|
Как видно, при помощи `${…}` можно вставлять как и значение переменной `${apples}`, так и более сложные выражения, которые могут включать в себя операторы, вызовы функций и т.п. Такую вставку называют "интерполяцией".
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -88,7 +88,9 @@ let str = f`Sum of ${apples} + ${oranges} =\n ${apples + oranges}!`;
|
||||||
Это нужно в тех случаях, когда функция шаблонизации хочет произвести обработку полностью самостоятельно (свои спец. символы?). Или же когда обработка спец. символов не нужна -- например, строка содержит "обычный текст", набранный непрограммистом без учёта спец. символов.
|
Это нужно в тех случаях, когда функция шаблонизации хочет произвести обработку полностью самостоятельно (свои спец. символы?). Или же когда обработка спец. символов не нужна -- например, строка содержит "обычный текст", набранный непрограммистом без учёта спец. символов.
|
||||||
[/smart]
|
[/smart]
|
||||||
|
|
||||||
Функция может как-то преобразовать строку и вернуть новый результат.
|
Как видно, функция имеет доступ ко всему: к выражениям, к участкам текста и даже, через `strings.raw` -- к оригинально введённому тексту без учёта стандартных спец. символов.
|
||||||
|
|
||||||
|
Функция шаблонизации может как-то преобразовать строку и вернуть новый результат.
|
||||||
|
|
||||||
В простейшем случае можно просто "склеить" полученные фрагменты в строку:
|
В простейшем случае можно просто "склеить" полученные фрагменты в строку:
|
||||||
|
|
||||||
|
@ -116,11 +118,11 @@ let oranges = 5;
|
||||||
alert( str`Sum of ${apples} + ${oranges} = ${apples + oranges}!`);
|
alert( str`Sum of ${apples} + ${oranges} = ${apples + oranges}!`);
|
||||||
```
|
```
|
||||||
|
|
||||||
Функция `str` в примере выше делает то же самое, что обычные обратные кавычки. Но, конечно, можно пойти намного дальше.
|
Функция `str` в примере выше делает то же самое, что обычные обратные кавычки. Но, конечно, можно пойти намного дальше. Например, генерировать из HTML-строки DOM-узлы (функции шаблонизации не обязательно возвращать именно строку).
|
||||||
|
|
||||||
Например, генерировать из HTML-строки DOM-узлы (функции шаблонизации не обязательно возвращать именно строку).
|
Или можно реализовать интернационализацию. В примере ниже функция `i18n` осуществляет перевод строки.
|
||||||
|
|
||||||
Или можно реализовать интернационализацию. В примере ниже функция `i18n` подбирает по строке вида `"Hello, ${name}!"` шаблон перевода `"Привет, {0}!"` (где `{0}` -- место для вставки параметра) и возвращает переведённый результат.
|
Она подбирает по строке вида `"Hello, ${name}!"` шаблон перевода `"Привет, {0}!"` (где `{0}` -- место для вставки параметра) и возвращает переведённый результат со вставленным именем `name`:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
|
@ -147,12 +149,16 @@ function i18n(strings, ...values) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Пример использования
|
// Пример использования
|
||||||
|
*!*
|
||||||
let name = "Вася";
|
let name = "Вася";
|
||||||
|
|
||||||
// Перевести строку
|
// Перевести строку
|
||||||
alert( i18n`Hello, ${name}!` ); // Привет, Вася!
|
alert( i18n`Hello, ${name}!` ); // Привет, Вася!
|
||||||
|
*/!*
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Итоговое использование выглядит довольно красиво, не правда ли?
|
||||||
|
|
||||||
Разумеется, эту функцию можно улучшить и расширить. Функция шаблонизации -- это своего рода "стандартный синтаксический сахар" для упрощения форматирования и парсинга строк.
|
Разумеется, эту функцию можно улучшить и расширить. Функция шаблонизации -- это своего рода "стандартный синтаксический сахар" для упрощения форматирования и парсинга строк.
|
||||||
|
|
||||||
## Улучшена поддержка юникода
|
## Улучшена поддержка юникода
|
||||||
|
@ -253,23 +259,24 @@ alert( "\u{20331}" ); // 𠌱, китайский иероглиф с этим
|
||||||
|
|
||||||
Например, на основе обычного символа `a` существуют символы: `àáâäãåā`. Самые часто встречающиеся подобные сочетания имеют отдельный юникодный код. Но отнюдь не все.
|
Например, на основе обычного символа `a` существуют символы: `àáâäãåā`. Самые часто встречающиеся подобные сочетания имеют отдельный юникодный код. Но отнюдь не все.
|
||||||
|
|
||||||
Для генерации произвольных сочетаний используются два юникодных символа: основа и значок.
|
Для генерации произвольных сочетаний используются несколько юникодных символов: основа и один или несколько значков.
|
||||||
|
|
||||||
Например, если после символа `S` идёт символ "точка сверху" (код `\u0307`), то вместе будет "S с точкой сверху" `Ṡ`.
|
Например, если после символа `S` идёт символ "точка сверху" (код `\u0307`), то показано это будет как "S с точкой сверху" `Ṡ`.
|
||||||
|
|
||||||
Если нужен ещё значок над той же буквой (или под ней) -- без проблем. Просто добавляем соответствующий символ.
|
Если нужен ещё значок над той же буквой (или под ней) -- без проблем. Просто добавляем соответствующий символ.
|
||||||
|
|
||||||
К примеру, если добавить символ "точка снизу" (код `\u0323`), то будет "S с двумя точками сверху и снизу" `Ṩ` .
|
К примеру, если добавить символ "точка снизу" (код `\u0323`), то будет "S с двумя точками сверху и снизу" `Ṩ` .
|
||||||
|
|
||||||
В JavaScript-строке:
|
Пример этого символа в JavaScript-строке:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
alert("S\u0307\u0323"); // Ṩ
|
alert("S\u0307\u0323"); // Ṩ
|
||||||
```
|
```
|
||||||
|
|
||||||
Такая возможность добавить произвольной букве нужные значки, с одной стороны, необходима, чтобы не хранить все возможные сочетания (которых громадное число), а с другой стороны -- возникает проблемка -- можно представить одинаковый с точки зрения визуального отображения и интерпретации символ -- разными сочетаниями Unicode-кодов.
|
Такая возможность добавить произвольной букве нужные значки, с одной стороны, необходима, а с другой стороны -- возникает проблемка: можно представить одинаковый с точки зрения визуального отображения и интерпретации символ -- разными сочетаниями Unicode-кодов.
|
||||||
|
|
||||||
|
Вот пример:
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
alert("S\u0307\u0323"); // Ṩ
|
alert("S\u0307\u0323"); // Ṩ
|
||||||
|
@ -278,7 +285,7 @@ alert("S\u0323\u0307"); // Ṩ
|
||||||
alert( "S\u0307\u0323" == "S\u0323\u0307" ); // false
|
alert( "S\u0307\u0323" == "S\u0323\u0307" ); // false
|
||||||
```
|
```
|
||||||
|
|
||||||
В первой строке сначала верхняя точка, а потом -- нижняя, во второй -- наоборот. По кодам строки не равны друг другу. Но символ задают один и тот же.
|
В первой строке после основы `S` идёт сначала значок "верхняя точка", а потом -- нижняя, во второй -- наоборот. По кодам строки не равны друг другу. Но символ задают один и тот же.
|
||||||
|
|
||||||
|
|
||||||
С целью разрешить эту ситуацию, существует *юникодная нормализация*, при которой строки приводятся к единому, "нормальному", виду.
|
С целью разрешить эту ситуацию, существует *юникодная нормализация*, при которой строки приводятся к единому, "нормальному", виду.
|
||||||
|
@ -300,7 +307,7 @@ alert( "S\u0307\u0323".normalize() == "\u1e68" ); // true
|
||||||
|
|
||||||
Это, конечно, не всегда так, просто в данном случае оказалось, что именно такой символ в юникоде уже есть. Если добавить значков, то нормализация уже даст несколько символов.
|
Это, конечно, не всегда так, просто в данном случае оказалось, что именно такой символ в юникоде уже есть. Если добавить значков, то нормализация уже даст несколько символов.
|
||||||
|
|
||||||
Впрочем, для большинства практических задач информации, данной выше, должно быть вполне достаточно, но если хочется более подробно ознакомиться с вариантами и правилами нормализации -- они описаны в приложении к стандарту юникод [Unicode Normalization Forms](http://www.unicode.org/reports/tr15/).
|
Для большинства практических задач информации, данной выше, должно быть вполне достаточно, но если хочется более подробно ознакомиться с вариантами и правилами нормализации -- они описаны в приложении к стандарту юникод [Unicode Normalization Forms](http://www.unicode.org/reports/tr15/).
|
||||||
|
|
||||||
## Полезные методы
|
## Полезные методы
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue