Структуры данных

Массив – это тип данных, хранящий пронумерованные значения. Каждое пронумерованное значение называется элементом массива, а число, с которым связывается элемент, называется его индексом. Массивы JavaScript не типизированы, это значит, что элемент массива может иметь любой тип, причем разные элементы одного массива могут иметь разные типы. Помимо этого массивы JavaScript являются динамическими, это значит, что объявлять фиксированный размер не нужно и можно добавить новые элементы в любое время.

Создание массива

1. с помощью литерала массива

let empty = [];  //пустой массив
let numbers = [4, 1, 2, 5]; //массив с 5 числовыми элементами
let diff = [1.5, false, "текст"];  //массив с 3 элементами 
                                  //различного типа

2.вызов конструктора Array()

let b = new Array(); // []
let c = new Array(1, 3, 5, 8, "строка", true); 
        // [1, 3, 5, 8, "строка", true]
let d = new Array(5);
        //[undefined, undefined, undefined, undefined, undefined]

Чтение, запись и добавление элементов массива

let numbers = [4, 1, 2, 5];
numbers[0];// 4
numbers[10];//undefined


numbers[0] = 10; //изменили первый элемент массива - [10, 1, 2, 5]

numbers[6] = 7; //стало [4, 1, 2, 5, undefined, 7]

Ошибки нет!

Методы и свойства массивов

array.lengthчисло, на единицу превосходящее максимальный индекс массива

! Длина length – не количество элементов массива, а последний индекс + 1.

Методы и свойства массивов

array.pop() удаляет последний элемент из массива и возвращает его

array.push(value) добавляет элемент в конец массива и возвращает новую длину массива

array.shift() - удаляет из массива первый элемент и возвращает его

array.unshift(value) - добавляет элемент в начало массива и возвращает новую длину массива

let array = ['zero', 'one', 'two'];
console.log('1:', array.pop());
console.log('2:', array);
let A = ['zero', 'one', 'two'];
console.log('3:', A.push('newValue'));
console.log('4:', A);
let B = ['zero', 'one', 'two'];
console.log('5:', B.shift());
console.log('6:', B);
let D = ['zero', 'one', 'two'];
console.log('7:', D.unshift('oops'));
console.log('8:', D);
let array = [];
array[40] = 'foo';
console.log('9:', array.length);
let array = new Array(40);
console.log('10:', array.length);
console.log('11:', array[20]);
let superArray = [1, 2, 3, 4, 5, 6, 7];
console.log('12:', superArray.length);

superArray.length = 3;
console.log('13:', superArray.length);
console.log('14:', superArray);

Методы и свойства массивов

stirng.split(separator)разбивает строку на массив строк путём разделения ее указанной подстрокой (separator)

let str = "I like cats";
let array = str.split(" ");
console.log(array);//["I", "like", "cats"]

array.join(separator) объединяет все элементы массива в строку

let array = ["I", "like", "cats"];
let str = array.join(':');
console.log(str);// "I:like:cats"

Методы и свойства массивов

array.splice(index, count, elem1, elem2...)изменяет содержимое массива, удаляя существующие элементы и/или добавляя новые

let array = [1, 2, 3, 4, 5, 6, 7, 8];
let spl = array.splice(0, 2, 9, 10, 11, 12);
console.log(spl);// [1, 2]
console.log(array);// [9, 10, 11, 12, 3, 4, 5, 6, 7, 8]

array.slice(begin, end)копирует участок массива от begin до end, не включая end. Исходный массив при этом не меняется

let array = [1, 2, 3, 4, 5, 6, 7, 8];
let copyArray = array.slice(0,2);
console.log(copyArray);// [1, 2]

Методы и свойства массивов

array.indexOf(elem) / array.lastIndexOf(elem)/  - возвращает первый/последний индекс, по которому данный элемент может быть найден в массиве или -1, если такого индекса нет

let array = [1, 5, 2, 3, 4, 5, 6, 7, 5, 8];

console.log(array.indexOf(5));//1
console.log(array.lastIndexOf(5));//8

Методы и свойства массивов

array.sort() - сортирует элементы массива, ! приводя их к строке

let array = [1, 12, 33, 4, 15, 6, 7, 8];
array.sort();
console.log(array);//[1, 12, 15, 33, 4, 6, 7, 8]

array.reverse() - меняет порядок элементов массива на обратный

let array = [1, 12, 33, 4, 15, 6, 7, 8];

array.reverse();
console.log(array);//  [8, 7, 6, 15, 4, 33, 12, 1]

Методы и свойства массивов

array.sort(func) - сортирует элементы массива, используя функцию для сравнения двух элементов

let array = [1, 12, 33, 4, 15, 6, 7, 8];

function compare(a, b) {
  if (a > b) {
    return true
  } else {
    return false
  }
  //return a - b;
}

array.sort(compare);
console.log(array);// [1, 4, 6, 7, 8, 12, 15, 33]

array.sort((a,b) => a - b);

Методы и свойства массивов

array.concat(val1, val2,...) - возвращает новый массив, состоящий из массива, на котором он был вызван, соединённого с другими массивами и/или значениями, переданными в качестве аргументов

let array1 = [1, 2, 3];
let array2 = [4, 5, 6];

let result = array1.concat(array2, 7, 8);
console.log(result);// [1, 2, 3, 4, 5, 6, 7, 8]

"Перебирающие" методы массива

array.forEach(callback) -  используется для перебора массива

callback(item, index, array)

item - очередной элемент,

index - его индекс,

array - массив, который перебирается

let array = [1, 2, 3, 4];

array.forEach((item, index, array) => {
  console.log( item * 2);// 2 4 6 8 
});

"Перебирающие" методы массива

array.filter(callback) -  используется для фильтрации, согласно функции. Исходный массив при этом не измененяется

let array = [1, 2, 3, 4];

let filteredArray = array.filter( 
    (item, index, array) => item % 2 === 0 );

console.log(array);// [1, 2, 3, 4]
console.log(filteredArray);//[2, 4]

"Перебирающие" методы массива

array.map(callback) -  создает новый массив, согласно функции. Исходный массив при этом не измененяется

let array = [1, 2, 3, 4];

let result = array.map((item, index, array) => item * 2);

console.log(array);//[1, 2, 3, 4]
console.log(result);//[2, 4, 6, 8]

"Перебирающие" методы массива

array.every(callback) -возвращает true, если вызов callback вернёт true для каждого элемента массива 

let array = [1, 2, 3, 4];

let result = array.every((item, index, array) => item > 0);
console.log(result);//true

"Перебирающие" методы массива

array.some(callback) - возвращает true, если вызов callback вернёт true для какого-нибудь элемента массива

let array = [1, -2, -3, -4];

let result = array.some((item, index, array) => item > 0);
console.log(result);//true

"Перебирающие" методы массива

array.reduce(callback) - используется для последовательной обработки каждого элемента массива с сохранением промежуточного результата

callback(previousValue, currentItem, index, array);

let array = [1, -2, -3, -4];

let result = array.reduce(
    (previous, item, index, array) => previous + item, 100);
console.log(result);// 92

array.reduceRight(callback) - работает аналогично, но идёт по массиву справа-налево.

Объект  — это в первую очередь просто коллекция свойств , состоящая из пар ключ-значение. Причем ключом может быть только строка , а вот значением — любой тип данных.  Если значением является функция, то ее называют методом.

Создание объекта

1. с помощью литерала объекта

let obj = {};

let person = {
    name : 'Alex',
    age : 20
};

2.  вызов конструктора Object

let obj = new Object();

Чтение, запись и добавление/удаление свойств объекта

let obj = {};

obj.name = 'Bob';
obj['title'] = 'manager';
console.log(obj);//{name:"Bob", title:"manager"}

obj['name'] = 'Steave';
console.log(obj.name);//"Steave"

delete obj.title;
console.log(obj);//{name:"Steave"}
let variable = 10;

delete variable;

console.log(variable);

!!!

Перебор свойств объекта

1. цикл for...in перебирает все перечисляемые свойства объекта и его цепочки прототипов

let book = {
  title : "Alice's adventures 
                in wonderland",
  author : "Lewis Carroll",
  pages : 200
};

for (let prop in book) {
  console.log(book[prop])
}; 
//Alice's adventures in wonderland
//Lewis Carroll
//200

2. Object.keys(object) -  возвращает массив со всеми собственными объекта object.

let book = {
  title : "Alice's adventures 
            in wonderland",
  author : "Lewis Carroll",
  pages : 200
};

console.log(Object.keys(book));
// ["title", "author", "pages"]

Перебор свойств объекта

3. Object.getOwnPropertyNames() возвращает массив со всеми свойствами объекта

let book = {
  title : "Alice's adventures in wonderland",
  author : "Lewis Carroll",
  pages : 200
};
console.log(Object.getOwnPropertyNames(book));
// ["title", "author", "pages"]

console.log(Object.getOwnPropertyNames(Array.prototype));

// ["length", "constructor", "concat", "pop", "push", "shift", 
//"unshift", "slice", "splice", "includes", "indexOf", "keys", 
//"entries", "forEach", "filter", "map", "every", "some", "reduce", 
//"reduceRight", "toString", "toLocaleString", "join", "reverse", "sort", 
//"lastIndexOf", "copyWithin", "find", "findIndex", "fill"]

console.log(Object.keys(Array));//[]

!!!

Массивы и объекты передаются не по значению, а по ссылке!

let book = {
  title : "Alice's adventures 
        in wonderland",
  author : "Lewis Carroll",
  pages : 200
};

let myBook = book;
console.log(myBook.title);
//"Alice's adventures in wonderland"

myBook.pages = 190;
console.log(book.pages);//190
let array = [1, 2, 3, 4, 5];
let copyArray = array;
console.log(copyArray);// [1, 2, 3, 4, 5]

copyArray.push(6);
console.log(array);//[1, 2, 3, 4, 5, 6]
let book = {
  title : "Alice's adventures in wonderland",
  author : "Lewis Carroll",
  pages : 200
};

let myBook = book;
myBook.pages = 190;

myBook = {  
  author : "L.Carroll"
};

console.log(myBook);
//?

console.log(book);
// { title="Alice's adventures in wonderland", 
//author="Lewis Carroll", 
//pages=190}

Объект Dateпредставляет собой момент времени. Объекты даты Date основываются на значении количества миллисекунд, прошедших с 1 января 1970 года в часовом поясе UTC.

Создание

1.  new Date() - создает объект Date с текущей датой и временем

let now =  new Date();
console.log(now);
// Tue Mar 27 2018 21:48:44 GMT+0300 (Беларусь (зима))

2.  new Date(milliseconds) - Создает объект Date, значение которого равно количеству миллисекунд (1/1000 секунды), прошедших с 1 января 1970 года GMT+0.

let fiveYears = 5 * 365 * 24 * 60 * 60 * 1000;
let date =  new Date(fiveYears);
console.log(date);
// Date {Tue Dec 31 1974 03:00:00 GMT+0300 (Belarus Standard Time)}

3. new Date(year, month, date, hours, minutes, seconds, ms)

let date =  new Date(2011, 9, 6, 20, 45);
console.log(date);
// Date {Thu Oct 06 2011 20:45:00 GMT+0300 (Belarus Standard Time)}

Получение отдельных элементов даты

getFullYear() - год(4 цифры)

getMonth() - месяц ( от 0 до 11).

getDate() - число месяца, от 1 до 31.

getDay() -  номер дня в неделе, 0 - воскресенье

getHours(), getMinutes(), getSeconds(), getMilliseconds()

 соответствующие компоненты

let date =  new Date(2011, 9, 6, 20, 45);
console.log(date);
// Date {Thu Oct 06 2011 20:45:00 GMT+0300 
                        (Belarus Standard Time)}

console.log(date.getFullYear());//2011
console.log(date.getMonth());//9
console.log(date.getDate());//6

Работа с числами

Infinity – особенное численное значение, которое ведет себя в точности как математическая бесконечность ∞.

console.log( Infinity > 1234567890 ); // true
console.log( Infinity + 5 == Infinity ); // true
console.log( -1 / 0 );//-Infinity
console.log( 1e500 ); //Infinity

Если математическая операция не может быть совершена, то возвращается специальное значение NaN (Not-A-Number).

console.log( 0 / 0 ); // NaN
console.log(NaN == NaN);//false
console.log(NaN === NaN);//false

Функция isFinite(n) преобразует аргумент к числу и возвращает true, если это не NaN/Infinity/-Infinity:

console.log( isFinite(1) ); // true
console.log( isFinite(Infinity) ); // false
console.log( isFinite(NaN) ); // false

Приведение к числу

let testNumber = "123.456";
console.log(+testNumber); // 123.456


let strNumber = "23 bottles of beer";
console.log(+strNumber);//NaN

Функция parseInt и ее аналог parseFloat преобразуют строку символ за символом, пока это возможно.При возникновении ошибки возвращается число, которое получилось. Функция parseInt читает из строки целое число, а parseFloat – дробное.

console.log( parseInt('12px') ) // 12
console.log( parseFloat('12.3.4') ) // 12.3
let testNumber = 300;

testNumber.toString(2);//"100101100"
testNumber.toString(8);//"454"
testNumber.toString(10);//"300"
testNumber.toString(16);//"12c"
testNumber.toString(20);//"f0"

Math.floor

Округляет вниз

Math.ceil

Округляет вверх

Math.round

Округляет до ближайшего целого

Math.floor(25.5);//25
Math.ceil(25.5);//26
Math.round(25.5);//26
let num = 12.345676432;

num.toFixed(2);//"12.35"
num.toFixed(5);//"12.34568"
num.toFixed(15);//"12.345676431999999"
console.log( 0.1 + 0.2 );
        //0.30000000000000004
console.log( 0.1 + 0.2 > 0.3 );
        //true
console.log( 0.1.toFixed(20) ); 
        //0.10000000000000000555
console.log( 9999999999999999 );
        //10000000000000000

Тригонометрия

Встроенные функции для тригонометрических вычислений:

Math.acos(x) Возвращает арккосинус x (в радианах)

Math.asin(x) Возвращает арксинус x (в радианах)

Math.atan(x) Возвращает арктангенс x (в радианах)

Math.atan2(y, x) Возвращает угол до точки (y, x). 

Math.sin(x) Вычисляет синус x

Math.cos(x) Вычисляет косинус x

Math.tan(x) Возвращает тангенс x

Функции общего назначения

Math.sqrt(x) Возвращает квадратный корень из x.

Math.log(x) Возвращает натуральный (по основанию e) логарифм x.

Math.pow(x, exp) Возводит число в степень, возвращает xexp, например Math.pow(2,3) = 8. Работает в том числе с дробными и отрицательными степенями( Math.pow(4, -1/2) = 0.5)

Math.abs(x) Возвращает абсолютное значение числа

Math.exp(x) Возвращает ex, где e – основание натуральных логарифмов.

Math.max(a, b, c...) Возвращает наибольший из списка аргументов

Math.min(a, b, c...) Возвращает наименьший из списка аргументов

Math.random() Возвращает псевдослучайное число в интервале [0,1) – то есть между 0 (включительно) и 1 (не включая).

Строки

Созднание строк

let str1 = "First string";
let str2 = 'Second string';
let str3 = "123456789";
let str4 = "Double\n lines";

Экранирование спец символов

let str5 = 'I\'m a human after all';
let str6 = "Platform 9 3\\4";

Экранирование служит исключительно для правильного восприятия строки JavaScript. В памяти строка будет содержать сам символ без '\'.

Методы для работы со строками

let str7 = "Example";

console.log(str7[3]);//m
console.log(str7.charAt(0));//E
console.log(str7.length);//7

!!!

console.log("".charAt(0)); // "" пустая строка
console.log("" [0]);//undefined

Смена регистра

let str8 = "We will rock you";

console.log(str8.toUpperCase());//WE WILL ROCK YOU
consolee.log(str8.toLowerCase());//we will rock you

Поиск подстроки

let str9 = "We Will Rock You";

console.log(str9.indexOf("Will"));//3
console.log(str9.indexOf("rock"));//-1
console.log(str9.indexOf("l"));//5
console.log(str9.indexOf("W", 1));//3

Для поиска подстроки есть метод indexOf(подстрока[, начальная_позиция]).

Он возвращает позицию, на которой находится подстрока или -1, если ничего не найдено.

Получение подстроки

Метод substring(start, end) возвращает подстроку с позиции start до, но не включая end. Если аргумент end отсутствует, то идет до конца строки.
Отрицательные аргументы интерпретируются как равные нулю.

Слишком большие значения усекаются до длины строки.

Кроме того, если start > end, то аргументы меняются местами, т.е. возвращается участок строки между start и end

let str10 = "I'm feeling good";

console.log(str10.substring(2, 15));//m feeling goo
console.log(str10.substring(22, 5));//eeling good
console.log(str10.substring(4));//feeling good
console.log(str10.substring(45));//undefined
console.log(str10.substring(-1));//I'm feeling good

Получение подстроки

substr(start [, length]) Первый аргумент имеет такой же смысл, как и в substring, а второй содержит не конечную позицию, а количество символов. Если второго аргумента нет – подразумевается «до конца строки».

let str11 = "I'm feeling good";

console.log(str10.substr(2, 15));//m feeling goo
console.log(str10.substr(22, 5));//undefined
console.log(str10.substr(4));//feeling good
console.log(str10.substr(-10));//eling good

slice(start [, end])

Возвращает часть строки от позиции start до, но не включая, позиции end. Смысл параметров – такой же как в substring.

Отрицательные значения отсчитываются от конца строки

let str12 = "I'm feeling good";

console.log(str12.slice(2, 15));//m feeling goo
console.log(str12.slice(22, 5));//""
console.log(str12.slice(4));//feeling good
console.log(str12.slice(45));//""
console.log(str12.slice(-1));//d

Char code

Все строки имеют внутреннюю кодировку Юникод

String.fromCharCode(code)

Возвращает символ по коду code

let str13 = "take me to church";

console.log(str13.charCodeAt(5));//109
console.log(String.charCode(1022));//ю

str.charCodeAt(pos)

Возвращает код символа на позиции pos. Отсчет позиции начинается с нуля.

let str14 = `Bingo!`;

console.log(str14);//Bingo!

Преимущества

1. Перевод строки

let str16 = "I
                 want 
                    to 
                        sleep";

console.log(str16);
// SyntaxError: Invalid or unexpected token
let str15 = `I
                 want 
                    to 
                        sleep`;

console.log(str15);
//I
//    want 
//        to 
//            sleep

2.Можно вставлять выражения

let str18 = "resting";

console.log(`I like ${str18}`);
//I like resting
let str19 = "resting";

console.log("I like" + " " + str19);
//I like resting
  • str.includes(s) – проверяет, включает ли одна строка в себя другую, возвращает true/false.
  • str.endsWith(s) – возвращает true, если строка str заканчивается подстрокой s.
  • str.startsWith(s) – возвращает true, если строка str начинается со строки s.
  • str.repeat(times) – повторяет строку str times раз.

Symbol

Примитивный тип данных Symbol служит для создания уникальных идентификаторов.

let sym = Symbol();

console.log(sym);//Symbol()
console.log(typeof sym);//symbol

!!! не new Symbol, а просто Symbol, так как это – примитив.

Каждый символ – уникален. У функции Symbol есть необязательный аргумент «имя символа». Его можно использовать для описания символа, в целях отладки

let symb = Symbol("oops");

console.log(symb.toString());//Symbol(oops)

Если у двух символов одинаковое имя, то это не значит, что они равны!!!!

console.log(Symbol("name") == Symbol("name")); // false

Существует «глобальный реестр» символов, который позволяет, при необходимости, иметь общие «глобальные» символы, которые можно получить из реестра по имени.

Для чтения (или создания, при отсутствии) «глобального» символа служит вызов Symbol.for(имя).

let name = Symbol.for("name");

console.log(Symbol.for("name") == name); // true

У вызова Symbol.for, который возвращает символ по имени, есть обратный вызов – Symbol.keyFor(sym). Он позволяет получить по глобальному символу его имя. Symbol.keyFor работает только для глобальных символов, для остальных будет возвращено undefined​

let globalSymbol = Symbol.for("name");

console.log( Symbol.keyFor(globalSymbol ) ); // name

Символы можно использовать в качестве имён для свойств объекта. Особенность символов в том, что если в объект записать свойство-символ, то оно не участвует в итерации

let user = {
  name: "Вася",
  age: 30,
  [Symbol.for("isAdmin")]: true
};

console.log( Object.keys(user) ); // ["name", "age"]
console.log( user[Symbol.for("isAdmin")] );//true
console.log(user.isAdmin);//undefined
console.log(Object.getOwnPropertySymbols(user));
//[Symbol(isAdmin)]

Cвойство-символ недоступно, если обратиться к его названию

Итератор

Итерируемые или, иными словами, «перебираемые» объекты – это те, содержимое которых можно перебрать в цикле. Для перебора таких объектов добавлен новый синтаксис цикла: for..of​

let arr = [1, 2, 3, 4, 5]; 

for (let item of arr) {
  console.log(item);// 1 2 3 4 5
}

Пример реализации итератора

range – диапазон чисел от from до to, надо «умным способом» перебрать его, чтобы for (let num of range) «перебирал» этот объект. При этом под перебором подразумеваем перечисление чисел от from до to.

let range = {
  from: 1,
  to: 5
};

Для возможности использовать объект в for..of нужно создать в нём свойство с названием Symbol.iterator (системный символ).

При вызове метода Symbol.iterator перебираемый объект должен возвращать другой объект («итератор»), который умеет осуществлять перебор.

По стандарту у такого объекта должен быть метод next(), который при каждом вызове возвращает очередное значение и проверяет, окончен ли перебор.

range[Symbol.iterator] = function() {
  let current = this.from;
  let last = this.to;

  // метод должен вернуть объект с методом next()
  return {
    next() {
      if (current <= last) {
        return {
          done: false,
          value: current++
        };
      } else {
        return {
          done: true
        };
      }
    }

  }
};

for (let num of range) {
  console.log(num); // 1, затем 2, 3, 4, 5
}

Здесь имеет место разделение сущностей:

  • Перебираемый объект range сам не реализует методы для своего перебора.
  • Для этого создаётся другой объект, который хранит текущее состояние перебора и возвращает значение. Этот объект называется итератором и возвращается при вызове метода range[Symbol.iterator].
  • У итератора должен быть метод next(), который при каждом вызове возвращает объект со свойствами:
    • value – очередное значение,
    • done – равно false если есть ещё значения, и true – в конце.

Генератор

Генераторы – новый вид функций в современном JavaScript. Они отличаются от обычных тем, что могут приостанавливать своё выполнение, возвращать промежуточный результат и далее возобновлять его позже, в произвольный момент времени.

 

Для объявления генератора используется новая синтаксическая конструкция: function*(функция со звёздочкой).

Её называют «функция-генератор» (generator function).

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

При запуске generateSequence() код такой функции не выполняется. Вместо этого она возвращает специальный объект, который как раз и называют «генератором».

При создании генератора код находится в начале своего выполнения.

Основным методом генератора является next(). При вызове он возобновляет выполнение кода до ближайшего ключевого слова yield. По достижении yield выполнение приостанавливается, а значение – возвращается во внешний код

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

let generator = generateSequence();

let one = generator.next();

console.log(JSON.stringify(one)); // {"value":1,"done":false}

Повторный вызов generator.next() возобновит выполнение и вернёт результат следующего yield:

let two = generator.next();

console.log(JSON.stringify(two)); // {"value":2,"done":false}

последний вызов завершит выполнение функции и вернёт результат return

let three = generator.next();

console.log(JSON.stringify(three)); // {"value":3,"done":true}

В этой главе мы рассмотрим работу с форматом JSON, который используется для представления объектов в виде строки.

Это один из наиболее удобных форматов данных при взаимодействии с JavaScript. Если нужно с сервера взять объект с данными и передать его клиенту, то в качестве промежуточного формата – для передачи по сети, почти всегда используют именно его.

В современных браузерах есть замечательные методы, знание тонкостей которых делает операции с JSON простыми и комфортными.

  • JavaScript-объекты { ... } или
  • Массивы [ ... ] или
  • Значения одного из типов:
    • строки в двойных кавычках,
    • число,
    • логическое значение true/false,
    • null.

Основные методы для работы с JSON в JavaScript – это:

  • JSON.parse – читает объекты из строки в формате JSON.
  • JSON.stringify – превращает объекты в строку в формате JSON, используется, когда нужно из JavaScript передать данные по сети.

Вызов JSON.parse(str) превратит строку с данными в формате JSON в JavaScript-объект/массив/значение.

let user = '{"name": "Вася", "age": 35, 
    "isAdmin": false, "friends": [0,1,2,3] }';
user = JSON.parse(user);

console.log(user);
    //{name: "Вася", age: 35, isAdmin: false, friends: Array(4)}
console.log( user.friends ); // [0, 1, 2, 3]

Для интеллектуального восстановления из строки у JSON.parse(str, reviver) есть второй параметр reviver, который является функцией function(key, value). Если она указана, то в процессе чтения объекта из строки JSON.parse передаёт ей по очереди все создаваемые пары ключ-значение и может возвратить либо преобразованное значение, либо undefined, если его нужно пропустить.

let str = '{"title":"Конференция","date":"2014-11-30T12:00:00.000Z"}';
let event = JSON.parse(str, (key, value) => {
  if (key == 'date') {
    return new Date(value);
  }
  return value;
});

console.log( event.date.getDate() );// 30

Метод JSON.stringify(value, replacer, space) преобразует («сериализует») значение в JSON-строку. При сериализации объекта вызывается его метод toJSON. Если такого метода нет – перечисляются его свойства, кроме функций

let room = {
  number: 23,
  occupy: function() {
    alert( this.number );
  }
};

let evt = {
  title: "Конференция",
  date: new Date(Date.UTC(2014, 0, 1)),
  room: room
}; 

console.log( JSON.stringify(evt) );
// {"title":"Конференция","date":"2014-01-01T00:00:00.000Z","room":{"number":23}}
let roomUpdated = {
  number: 23,
  toJSON: function() {
      return this.number;
    }
};

console.log( JSON.stringify(roomUpdated ) );// 23

Во втором параметре JSON.stringify(value, replacer) можно указать массив свойств, которые подлежат сериализации.

let userVasya = {
  name: "Vasya",
  age: 25,
  window: window
};

console.log( JSON.stringify(userVasya , ["name", "age"]) );
//{"name":"Vasya","age":25}

Для более сложных ситуаций вторым параметром можно передать функцию function(key, value), которая возвращает сериализованное value либо undefined, если его не нужно включать в результат

let userVasyan = {
  name: "Vasya",
  age: 25,
  window: window
};

let str = JSON.stringify(userVasyan, (key, value) => {
  if (key == 'window') {
     return undefined;
  }
  return value;
});

console.log( str );// {"name":"Vasya","age":25}

В методе JSON.stringify(value, replacer, space) есть ещё третий параметр space.

Если он является числом – то уровни вложенности в JSON оформляются указанным количеством пробелов, если строкой – вставляется эта строка.

let user = {
  name: "Vasyan",
  age: 25,
  roles: {
    isAdmin: false,
    isEditor: true
  }
};
let str = JSON.stringify(user, "", 4);

console.log( str );
// {
    "name": "Vasyan",
    "age": 25,
    "roles": {
        "isAdmin": false,
        "isEditor": true
    }
}

Деструктуризация

Деструктуризация (destructuring assignment) – это особый синтаксис присваивания, при котором можно присвоить массив или объект сразу нескольким переменным, разбив его на части.

Массив

let [firstName, lastName] = ["Вася", "Пупкин"];

console.log(firstName); // Вася
console.log(lastName);  // Пупкин

При таком присвоении первое значение массива пойдёт в переменную firstName, второе – в lastName, а последующие (если есть) – будут отброшены.

// первый и второй элементы не нужны
let [, , last] = "казнить нельзя помиловать".split(" ");

console.log(last); // помиловать

В коде выше первый и второй элементы массива никуда не записались, они были отброшены. Как, впрочем, и все элементы после третьего.

Если мы хотим получить и последующие значения массива, но не уверены в их числе – можно добавить ещё один параметр, который получит «всё остальное», при помощи оператора "..." («spread», троеточие):

let [first, second, ...rest] = "I'm only human after all".split(" ");

console.log(first); //I'm
console.log(second); //only
console.log(rest);  // ["human", "after", "all"]
// значения по умолчанию
let [firstName="Gadya", lastName="Petrovich"] = [];

console.log(firstName); // Gadya
console.log(lastName);  // Petrovich
let options = {
  title: "Menu",
  width: 100,
  height: 200
};

let {title, width, height} = options;

console.log(title);  // Menu
console.log(width);  // 100
console.log(height); // 200

Как видно, свойства options.title, options.width и options.height автоматически присвоились соответствующим переменным

Если хочется присвоить свойство объекта в переменную с другим именем, например, чтобы свойство options.width пошло в переменную w, то можно указать соответствие через двоеточие

let options = {
  title: "Menu",
  width: 100,
  height: 200
};

let {title, width: w, height: h} = options;

console.log(title);  // Menu
console.log(w);  // 100
console.log(h); // 200

Если каких-то свойств в объекте нет, можно указать значение по умолчанию через знак равенства =

let options = {
  title: "Menu"
};

let {title, width = 100, height = 200} = options;

console.log(title);  // Menu
console.log(width);  // 100
console.log(height); // 200
let options = {
  title: "Menu"
};

let {title, width: w = 100, height: h = 200} = options;

console.log(title);  // Menu
console.log(w);  // 100
console.log(h); // 200
let options = {
  title: "Меню",
  width: 100,
  height: 200
};

let {title, ...size} = options;
console.log(title);// Menu
console.log(size);// {title: "Меню", width: 100, height: 200}

Data structure

By Anna Protasevich

Data structure

  • 633