Translate

Поиск по этому блогу

вторник, 18 сентября 2018 г.

Работа с REPL. Основные команды.

REPL - read eval print loop это интерактивный компонент, который поставляется вместе с Node.js




При работе в Node.js часто приходится запускать целые файлы или части кода для тестирования. Для удобства можно использовать REPL, просто набрав в КС (здесь и далее - командная строка):

node


Нажать Enter.

Без ключевого слова var будет возвращать введенные выражения, а с var - undefined



Так происходит потому что в результате операции присваивания значения переменной не возвращает результат.

Вот интересный пример:



Ожидали увидеть true?

Не забывайте, что интерпретатор пойдет слева направо и вначале сравнит 3 и 2. Получит true. И только потом сравнит true и 1 и получит false

3>2==1 будет true, потому что при не строгом сравнении true==1

Можете проверить!

Многострочный и сложный JS код

JS код можно набирать в REPL точно так же как в обычном файле, включая необходимые инструкции для импорта модулей.

Пример с модулем Query String:



Переменная qs без var и нажать Enter. Пока мы работаем без var, то сразу видим результат. В данном случае это интерфейс объекта querystring.

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

Здесь можно также вставлять блоки кода - правая кнопка мыши и выбрать "Вставить".

Основной объект Node.js global на официальном сайте Node.js документирован довольно слабо. Чтобы это испавить, вы можете посмотреть всё информацию об этом объекте просто набрав:

console.log(global);


Или:

gl = global;


Для перехода по уже набранным вами командам, можно воспользоваться стрелками "вверх" - "вниз" - . Выбрать нужную и нажать Enter.

Управление REPL с помощью команд.
  • Ctrl + C - Завершает выполнение текущей команды. Повторное нажатие - выход из REPL.
  • Ctrl + D или написать в консоли .exit - Выход из REPL.
  • Tab - Автоматическое завершение имени глобальной или локальной переменной.
  • - Переход вверх по списку введенных команд.
  • - Переход вниз по списку введенных команд.
  • _ -(нижнее подчеркивание) - ссылка на результат вычисления после выражения.


Ниже приведу список команд для ввода в поле REPL:

  • .break - Если вы запутались с введением многострочного кода, эта команда вернет вас к самому началу, но весь многострочный код будет потерян.
  • .clear - Перезапуск объекта контента и очистка любого многострочного выражения. Эта команда по сути запускает сеанс с самого начала.
  • .exit - Выход из REPL
  • .help - Вывод всех доступных команд.
  • .save - Сохранение текущего REPL сеанса в файле.
  • .load путь/к/файлу.js - Загрузка файла в текущий сеанс (


Команда .save путь/к/файлу/для/сохранения.js сохраняет в файле все, что было введено в текущий объект контента. Пока не будет специально создан новый объект контента или использована команда .clear. Контент включает в себя все, что было введено в текущий REPL сеанс.

Node компонент REPL является удобным интерактивным средством упрощающим разработку. REPL позволяет не только проверять код перед его включением в файлы, но и создавать приложения в интерактивном режиме, сохраняя результаты после завершения.

Еще одним полезным свойством REPL является возможность создания собственной, нестандартной версии. Позволяющей исключить ответы в виде undefined и предварительно загружать модули.

Если вы собираетесь использовать REPL для разработки, то не забывайте чаще сохранять свою работу!



                                                                                                                                                             

вторник, 11 сентября 2018 г.

ES6: Объекты (VIII).

Объекты в ES6

Рассмотрим нововведения, которые помогут нам работе с объектами в ES6.



Все материалы по ES6


В отличии от других языков, в JavaScript мы очень часто работаем с литералами объектов. То есть с простыми объектами, которые не являются представителями какого-либо класса, а представляют из себя набор свойств и значений.

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

Первое, что мы сделаем, это запустим скрипт Babel, который будет следить за файлами и при их изменении создавать свежие версии.

Откроем папку проекта в командной строке (КС). Вводим команду:

npm run watch


И нажать Enter

Последние версии браузеров поддерживают все новвовведения для объектов без транспиляции. Измененый код нас будет интересовать в порядке ознакомления.

В папке src создадим файл objects.js и сразу укажу его в файле index.html

<script src="src/objects.js"></script>

Начнем со свойств.

Допустим, имеется три переменные - имя, фамилия и электронная почта.


let firstName = "Bill",
    lastName = "Smit",
    email = "bill@gmail.com";



Далее, создадим объект в котором в качестве свойств мы укажем названия переменных:


let firstName = "Bill",
    lastName = "Smit",
    email = "bill@gmail.com";

let person = {
 firstName: firstName,
 lastName: lastName,
 email: email
};

console.log( person );



И в конце мы вывели значения объекта person в консоли браузера.



В ES6, если свойство совпадает с названием переменной, то мы можем указать только свойство. Значение автоматически вставится из переменной с таким же названием.

Объекст person мы можем записать так:


let person = {
 firstName,
 lastName,
 email
};



Сохраняем, и видим тотже результат, что и на фото выше.

Давайте посмотрим на то, что транспилировал Babel

dist/object.js


"use strict";

var firstName = "Bill",
    lastName = "Smit",
    email = "bill@gmail.com";

var person = {
 firstName: firstName,
 lastName: lastName,
 email: email
};

console.log(person);



Он сделал тоже самое, что у нас было изначально!

Теперь перейдем к методам

Создание методов тоже стало немного проще.

Давайте добавим нашему объекту метод.


let firstName = "Bill",
   lastName = "Smit",
   email = "bill@gmail.com";

let person = {
 firstName,
 lastName,
 email,
 say: function() {
  console.log(`Hello, my name is ${firstName} ${lastName}`);
 }
};

console.log( person );
person.say();





В ES6 мы можем немного упростить написание метода, а именно - убрать слово function и двоеточие, оставив только круглые скобки ()


 say() {
  console.log(`Hello, my name is ${firstName} ${lastName}`);
 }


В консоле мы увидим тотже самый результат.

Если посмотреть на транспилированный код, то можно увидеть то, что Babel сделал все ,как и было изначально:

dist/object.js


"use strict";

var firstName = "Bill",
    lastName = "Smit",
    email = "bill@gmail.com";

var person = {
 firstName: firstName,
 lastName: lastName,
 email: email,
 say: function say() {
  console.log("Hello, my name is " + firstName + " " + lastName);
 }
};

console.log(person);
person.say();



Как вы уже знаете, в JavaScript свойства объекта, или метод, можно указать двумя способами: чрез точку, или через квадратные скобки.

Добраться до свойства firstName объекта person мы можем используя точку - person.firstName или квадратные скобки - person['firstName'].

Если мы используем квадратные скобки, то мы можем либо строкой указать название сво-ва, либо название переменной, в которой указано это сво-во.

Создадим новую переменную в которой в качестве значения укажем название свойства.

let property = 'firstName';

Далее в квадратных скобках мы можем указать название переменной

person[property]; Это будет тоже самое, что и person['firstName'];

Теперь, если поменять значение переменной на lastName

let property = 'lastName';

Так мы получим доступ к свойству lastName

Так можно сделать только в том случае если объект уже существует!!!


Но в ES6 мы можем использовать квадратные скобки прями внутри объекта. Тем самым динамически указывать названия сво-ва.

Например:


let property = 'lastName';
person[property]; // person['firstName']
person = {
    [property]: 'Bill'
};


В данном случае person будет присвоен объект, в котором сво-ва мы указываем динамически из переменной property.

Для того, чтобы указать firstName нам нужно указать в параменной let property - 'firstName'.

Вот так:

let property = 'lastName';

и так далее. Мы можем динамически менять значение переменной.

Для более практичного примера я создам функцию createCar, которая будет принимать название свойства - property и значение свойства - value.

В функции мы создадим простой объект с одним свойством и вернем его.

Как мы и говорили, в ES5 после создания объекта можно динамически указать название свойства.

Вначале создаем объект - var car ={}

Далее в квадратных скобках указываем его свойства car[property]

и присваеваем ему значение value

car[property] = value

И возвращаем объект - return car

Чтобы посмотреть на результат console.log(createCar('vin', 1));


function createCar( property, value ) {
 var car = {};
 car[property] = value;
 return car;
};

console.log(createCar('vin', 1));





В консоле мы увидим объект со свойством vin и значением - 1.

В ES6 мы можем указать значение свойства прямо в литерале объекта.

Поэтому мы сразу вернем объект - return

и в свойствахв квадратных скобках мы указываем переменную [property] со значением value.

[property]:value


function createCar( property, value ) {
 return{
  [property]: value
  };
};
console.log(createCar('vin', 1));



В консоле мы получим тотже самый результат.

И теперь давайте посмотри как это все сгенерировал Babel

dist/object.js

function _defineProperty(obj, key, value) { 
if (key in obj){ 
Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });
 } 
else { 
obj[key] = value; } return obj;
 }

function createCar(property, value) {
 return _defineProperty({}, property, value);
};
console.log(createCar('vin', 1));



Функция _defineProperty обращается к глобальному объекту, чтобы создать свойства.

Благодаря новому синтаксису нам нет в этом необходимости и записи стали проще.

И, так как мы используем название переменной, у нас появились новые возможности, которых не было раньше при создании объекта.

Мы можем теперь добавить нижнее подчеркивание к названию совойства ['_' + property]: value


function createCar( property, value ) {
 return{
  [property]: value,
  ['_' + property]: value
  };
};
console.log(createCar('vin', 1));



У объекта появилось новое свойство - _vin



Или мы можем использовать метод toUpperCase()


function createCar( property, value ) {
 return{
  [property]: value,
  ['_' + property]: value,
  [property.toUpperCase()]: value
  };
};
console.log(createCar('vin', 1));



Результат - новое свойство VIN:



Можно динамически указать название метода:

function createCar( property, value ) {
 return{
  [property]: value,
  ['_' + property]: value,
  [property.toUpperCase()]: value,
  ['get' + property]() {
       return this[property];
      }
  };
};
console.log(createCar('vin', 1));



Теперь у обекта появился динамически заданный метод getvin



В JavaScript помимо свойств и методов, можно создавать специальные свойства, которые внутри объектов выглядят и работают как методы, но снаружи работаеют как свойства.

Эти суппер-свойства называются get и set или геттер и сеттер.

Давайте вернемся к объекту person и добавим ему оба этих метода.

Вначале добавим их в стиле ES5:

Чтобы добаить свойство мы воспользуемся объектом Objcts методом .defineProperty()

Первым параметром будет объект которому создаются свойства - person, а вторым параметром название свойства 'fullName', а далее принимается объект в котором это свойство описаывается.

В этом объестк первым свойством будет get - функция, которая ничего не принимает, но возвращает (this.firstName + ' ' + this.lastName).

Перед тем, как посмотреть результат я закоментирую код, который не относится к объекту person


Object.defineProperty(person, 'fullName', {
    get: function() {
        return this.firstName + ' ' + this.lastName;
    }

});



Сохраняем. Смотрим в консоле.

Теперь у нашего объекта person появилось новое свойство - fullName (на фото ниже оно подчеркнуто.

Теперь если мы обратимся к нему через точечную нотацию в консоле - person.fullName , то получим "Bill Smit", как на фото ниже в рамке.



Обратите внимание что get является функцие, но при этом мы не используем круглые скобки.

Внутри объекта - это метод, а снаружи это свойства!

Особого смысла метод set, в данном случае, не имеет, но для полноты картины, мы его определим. Его отличие от get в том. что set получает значение. Его можно назвать как угодно - это просто переменная. В нашем случае - value. В теле метода мы можем что-либо сделать - напрмер присвоить свойство this.firstName = value;


let person = {
    firstName,
    lastName,
    email,
    sayHello() {
        console.log(`Hi my name is ${this.firstName} ${this.lastName}`);
    },
    get fullName() {
        return this.firstName + ' ' + this.lastName;
    },
    set fullName(value) {
        this.firstName = value;
    }
};



Сохраним и посмотрим в консоле:



  1. - мы увидим, что у нашего объекта появились два метода (геттер и сеттер).
  2. - назначим новое значение свойству fillName - > person.fullName = "John";
  3. - вывдеме значение этого свойства - person.fullName


Для того, чтобы переписать код на ES6, все что нам нужно сделать это добавить к нашему объекту person


let person = {
    firstName,
    lastName,
    email,
    sayHello() {
        console.log(`Hi my name is ${this.firstName} ${this.lastName}`);
    },
    get fullName() {
        return this.firstName + ' ' + this.lastName;
    },
    set fullName(value) {
        this.firstName = value;
    }
};



Результат в консоли будет тот же.



Чаще всего свойства get и set не присваиваются простым объектам. Они присваиваются, как правило, объектам - представителям какого-нибудь класса.

В ES6 добавили поддержку классов. О них мы поговорим позже.



                                                                                                                                                             

понедельник, 10 сентября 2018 г.

ES6: Цикл for...of (VII).

Цикл for...of

Сегодня мы рассмотрим цикл for...of, благодаря которому мы можем итерировать массивы и другие структуры.



Все материалы по ES6


Первое, что мы сделаем это запустим скрипт Babel, который будет следить за файлами и при их изменении создавать свежие версии.

Откроем папку проекта в командной строке (КС). Вводим команду:

npm run watch


И нажать Enter

Последние версии браузеров поддержвают параметры по умолчанию без транспиляции. Изменнеый код нас будет интересовать в порядке ознакомления.

В папке src создадим файл for.js и сразу укажу его в файле index.html

<script src="src/for.js"></script>

Последние версии браузеров поддерживают цикл for...of без транспиляции.

Цикл for...of очень похож на цикл for...in.

Разница в том, что for...of перебирает значения, в то время как for...in - ключи.

Если вы забыли как работает цикл for...in, то можно посмотреть это на примере:

Создадим массив с некоторыми значениями и попробуем вывести значения в консоль, используя цикл for...in и выведем сам массив.


let animals = ['cat', 'dog', 'hamster', 'fish', 'goat'];
for( animal in animals ) {
 console.log(animal);
};
console.log(animals);



В консоли мы увидим:



Вывели циклом for...in ключи массива, а нам нужно значения.

Конечно, имея ключ мы можем сделать так:


let animals = ['cat', 'dog', 'hamster', 'fish', 'goat'];
for( let animal in animals ) {
 console.log(animal);
};

for( let index in animals ) {
 console.log( animals[index]);
};

console.log(animals);





Мы так же можем воcпользоваться методом for...of


let animals = ['cat', 'dog', 'hamster', 'fish', 'goat'];
for( let animal in animals ) {
 console.log(animal);
};

for( let index in animals ) {
 console.log( animals[index]);
}

for( let animal of animals ) {
 console.log( animal );
}

console.log(animals);





Таким образом мы сможем легко вывоить значения циклом без использования кллючей.

Давайте посмотрим на то, что сгенерировал Babel


'use strict';

var animals = ['cat', 'dog', 'hamster', 'fish', 'goat'];
for (var animal in animals) {
 console.log(animal);
};

for (var index in animals) {
 console.log(animals[index]);
}

var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;

try {
 for (var _iterator = animals[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
  var _animal = _step.value;

  console.log(_animal);
 }
} catch (err) {
 _didIteratorError = true;
 _iteratorError = err;
} finally {
 try {
  if (!_iteratorNormalCompletion && _iterator.return) {
   _iterator.return();
  }
 } finally {
  if (_didIteratorError) {
   throw _iteratorError;
  }
 }
}

console.log(animals);



Если честно, то совсем нет желания разбираться с тем, что там происходит. :-)

Меня вполне устраивает цикл for...of!

Помимо массивов цикл for...of позволет итеррировать и новые структуры, которые будут добавлены в ES6 - это объекты set и map.

О них чуть позже.



                                                                                                                                                             

воскресенье, 9 сентября 2018 г.

ES6: Параметры функции (VI).

Параметры функции





Все материалы по ES6


В JavaScript работа с параметрами функции очень гибкая. Например: Ничто не помешает отправить в функцию больше, или меньше аргументов, чем нужно. Но "Большая сила несет за собой большую ответсвенность!"

И в больших приложениях на JavaScript такая гибкость может создать проблемы. В ES6 есть два нововведения, касающихся параметров функции, которые могут сделать работу с ними более удобной и понятной.

  • Параметры по умолчанию (default parameters).
  • Оставшиеся параметры (rest parameters).

Параметры по умолчанию (default parameters).

Первое что мы сделаем это запустим скрипт Babel, который будет следить за файлами и при их изменении создавать свежие версии.

Откроем папку проекта в командной строке (КС). Вводим команду:

npm run watch


И нажать Enter

Последние версии браузеров поддержвают параметры по умолчанию без транспиляции. Изменнеый код нас будет интересовать в порядке ознакомления.

В папке src создадим файл parameters.js и сразу укажу его в файле index.html

<script src="src/parameters.js"></script>

Лучше всего понять это на примере:

Создадим функцию greet(), которая будет принимать два параметра greeting, name, а в консоле выводить сообщение приветствия.

console.log(`${greeting} ${name}`);

Здесь мы воспользовались шаблонной строкой.

Теперь можно вызвать функцию со следующими аргументами:

greet("Hi", "Bill"); parameters.js


function greet(greeting, name) {
 console.log(`${greeting} ${name}`);
};
greet("Hi", "Bill");



Результат будет вывод в консоль сообщения Hi Bill, как на фото ниже.



Теперь попробуем опустить один из парамеров.

greet("Hi");

В консоле мы увидим Hi undefined.



Так произошло, потому что мы не отправили параметр и ему присвоено значение undefined.

Мы можем отправить значение undefined сами.

greet(undefined, "Bill");

Результат:



И как можно предположить, если вызвать эту функцию вообще без аргументов, то в консоле получим undefined undefined.

Для того, чтобы функция работала правильно, нам следует проверить значения параметров перед тем, как мы ее используем.

Это можно сделать несколькими способами. Для того, чтобы лучше понять - воспользуемся самым объемным и запутанным. :-)


function greet(greeting, name) {
    if (greeting !== undefined && name !== undefined) {
        console.log(`${greeting} ${name}`);
    } else if (greeting === undefined && name !== undefined) {
        console.log(`Hello ${name}`);
    } else if (greeting !== undefined && name === undefined) {
        console.log(`${greeting} friend`);
    } else {
        console.log('Hello friend');
    }
}



Я думаю, что здесь все понятно, не смотря на относительно большой блок кода. Здесь идет обычная проверка переданных в функцию аргументов в блоках if, и если один из параметров undefined, то тогда ему назначаем новый параметр.

Запустим, чтобы убедиться и увидим в консоле:



Это значит, что функция работает правильно!

Но данный алгоритм ужастен и так писать код в JavaScript ненужно!

Очень много кода ушло только на то, чтобы проверить значения двух параметров.

А если их много? Пять! Десять!

Мы можем намного упростить код используя параметры по умолчанию!

Это можно сделать очень просто!


function greet(greeting = "Hello", name = "friend") {
 console.log(`${greeting} ${name}`);
};

greet("Hi", "Bill");
greet("Hi");
greet(undefined, "Bill");



В результате мы увидим в консоле:



Теперь можно посотреть на транспилированный код - dist/parameters.js


"use strict";

// function greet(greeting, name) {
//  console.log(`${greeting} ${name}`);
// };
// greet("Hi", "Bill");
// greet("Hi");
// greet(undefined, "Bill");


// function greet(greeting, name) {
//     if (greeting !== undefined && name !== undefined) {
//         console.log(`${greeting} ${name}`);
//     } else if (greeting === undefined && name !== undefined) {
//         console.log(`Hello ${name}`);
//     } else if (greeting !== undefined && name === undefined) {
//         console.log(`${greeting} friend`);
//     } else {
//         console.log('Hello friend');
//     }
// }

function greet() {
 var greeting = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "Hello";
 var name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "friend";

 console.log(greeting + " " + name);
};

greet("Hi", "Bill");
greet("Hi");
greet(undefined, "Bill");



Babel сделал то, что мы сделали бы и сами. Использовал переменные, оператор "или" - || и тернарный оператор - ?.

Теперь перейдем к оставшимся параметрам.



Оставшиеся параметры (rest parameters)

Предположим, что требуется написать функцию, которая складывает числа. Заранее мы не знаем сколько будет параметров. Поэтому вызов функции может выглядт следующим образом:

sum(5, 7, 2, 10);

Теперь напишем саму функцию. Но, что нам делать с параметрами, если мы не знаем сколько их будет?

До ES6 мы использовали объект arguments. Данный объект не указывается в списке параметров и доступен в любой функции.


function sum(){
 console.log(arguments);
};
sum(5, 7, 2, 10);



Давайте посмотрим на этот объект в консоле.



С первого взгляда может показаться, что это массив, но это не так.

Это объект названия свойств которого представляют числа.

В этом можно убедиться используя оператор instanceof


function sum(){
 console.log(arguments instanceof Array);
};
sum(5, 7, 2, 10);



В консоле мы увидим false - подтверждение того, что arguments не является массивом.

Для того, чтобы итерировать arguments мы мжем использовать цикл for, но мне кажется, что намного проще использовать метод forEach, который доступен всем массивам. Пробелам лишь в том, что arguments не массив. У него нет этого метода.

Мы можем сделать следующее:

Используя проттип объекта Array - Array.prototype мы можем использовать метод call() метода forEach forEach.call(). Туда передадим объект arguments и функцию обратного вызова, которая примет параметры value (index и array но они нам не нужны).

Нам потребуется переменная. И так как мы пишем в ES5, то мы объявим ее через var.


function sum(){
 console.log(arguments instanceof Array);

 var sum = 0;
 Array.prototype.forEach.call(arguments, function(value){
  sum += value;
 });
 console.log(sum);
};
sum(5, 7, 2, 10); //24


Эта функция выведет в консоль 24.

В ES6 в таком написании нет необходимости, но знать, как работает эта функция нужно!

Если мы пишем код на ES6, то мы можем воспользоваться оставшимися параметрами.

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


function sum(...values){
    console.log(values);
}


Очень похоже на оператор разворота, но работает по другому.

Если оператор разворота разворачивает массив и представляет аргументы по отдельности, то синтаксис оставшихся параметров наоборот - превращает отдельные элементы в массив.

Таким образом values будет полноценным массивом.

Мы можем посмотреть на него в консоле и увидет значения массива.



Для того, чтобы убедиться в том, что это массив, мы можем воспользоваться оператором instanceof

function sum(...values){
 console.log(values instanceof Array); //true
}



В коносле мы увидим true.

Тепер мы перепишем нашу функцию используя ES6.

Так как это массив мы можем использовать метод forEach сразу на values.


function sum(...values){
 console.log(values instanceof Array);
 let sum = 0;
 values.forEach(function(value){
  sum += value;
 });
 console.log(sum); //24
}



В консоль выведет снова - 24!

Мы можем еще больше упростить функцию, воспользовавшись методом - reduce, который есть у всех массивов. Данный метод можно использовать, чтобы сложить элементы массива.

Функция обратного вызова в качестве первого параметра принимает предыдущее значение - prevValue, currentValue


function sum(...values) {
    console.log(values.reduce(function(prevValue, currentValue) {
        return prevValue + currentValue;
    }));
}


sum(5, 7, 2, 10);



Данный код выведет -24.

Шпаргалка по ES6





                                                                                                                                                             

суббота, 8 сентября 2018 г.

ES6 Template Strings. Шаблонные строки (V).

Template Strings. Шаблоны или шаблонные строки.





Все материалы по ES6


Еще одним приятным добавлением в ES6 являются шаблоны или шаблонные строки (template literals or template strings).

Они представлюят функционал очень похожий на шаблонизаторы.

Первое что мы сделаем это запустим скрипт Babel, который будет следить за файлами и при их изменении создавать свежие версии.

Откроем папку проекта в командной строке (КС). Вводим команду:

npm run watch


И нажать Enter

Последние версии браузеров поддерживают шаблоны без транспиляции. Измененный код нас будет интересовать в порядке ознакомления.

В папке src создадим файл templates.js и сразу укажу его в файле index.html

<script src="src/templates.js"></script>

Сначала в примере я воспользуюсь простой строкой, а потом заменю её на шаблонную.

В этом файле мы создадим функцию greet(name), которая будет принимать имя.

Функция выведет сообщение "Hello " + name в консоле браузера.


function greet( name ) {
 console.log("Hello " + name );
};

greet("Bill");



В консоле мы увидим:



Теперь давайте изменим простую строку на шаблонную.

Для этого нам нужно заменить обычные кавычки на обратные.

Клавиша обратных кавычек ` находится на клавиатуре в верхнем левом углу - буква Ё в русской раскладке.

Поместим весь наш "вывод" в обратные кавычки, удалим плюс оставим пробел и поместим нашу переменную в фигурные скобки -{}, поставив перед ними знак доллора ${имя_переменной}.

Сочетание ${} еще называется местозаполнителем


function greet( name ) {
 console.log(`Hello ${name}` );
};

greet("Bill");



Если посмотреть на резулльтат в браузере, то он будет таким же, но при этом использовать шаблон куда легче. Главное - не забывать ставить пробелы и переносы строк, которые автоматически будут отображаться при выводе в консоль.

Если посмотреть на тип шаблонной строки используя оператор typeof:

console.log(typeof`Hello ${name}` ); // string

Это значит, что шаблоны такие же строки! То есть - мы можем с нми использовать все методы строк!

Например: Мы можем вывести сообщение так, чтбы все буквы были заглавными.


function greet( name ) {
 console.log(`Hello ${name}`.toUpperCase() );
};

greet("Bill");





Теперь давайте посмотрим на то, что создал Babel dist/templates.js


"use strict";

function greet(name) {
 console.log(("Hello " + name).toUpperCase());
};

greet("Bill");



Он сделал то, что мы с вами и сами бы написали, если бы использовали обычную строку.

Многострочность.

Шаблонные строки, также поддерживают многострочность. То есть их можно спокойно переносить на несколько строк.

Посмотрим на примере.

Мы создадим новую функцию, которая будет принимать параметры - откого, кому, тема и сообщение.

И вызовем эту функцию с некторыми аргументами:


function createEmail( to, from, subject, message ) {
 console.log(`
   to: ${to}
   from: ${from}
   subject: ${subject}
   message: ${message}
  `);
};

createEmail("john@mail.com", "elen@mail.com", "Hello", "How are you?");





Как вы можете убедиться, вывод в консоле состоялся именно так, как мы и написали - в 4 строки и с соблюдением табуляции.

Теперь посмотрим на то, как это сгенерировал Babel -> dist/templates.js


function createEmail(to, from, subject, message) {
 console.log("\n\t\t\tto: " + to + "\n\t\t\tfrom: " + from + "\n\t\t\tsubject: " + subject + "\n\t\t\tmessage: " + message + "\n\t\t");
};

createEmail("john@mail.com", "elen@mail.com", "Hello", "How are you?");



Создадим функцию, которая будет скалдывать два числа и выводить в консоль в виде арифметического примера.

Вызовем функцию с призвольными числами:


function add( x, y ) {
 console.log(`${x} + ${y} = ${x + y}`)
}

add( 4, 7 );



Здесь первый +, является частью строки. Второй + является частью выражения и складывает наши переменные.

В результате мы увидм:



А что если мы полчаем данные от пользователя со страницы?

Данные будут в виде строк.

Вызовем функцию так add( '4', '7' );

Резуьтат:



так получилось, потому что мы складывали строки.

Для того, чтобы убедиться. что мы складываем именно числа, мы можем применить функцию parseInt()


function add( x, y ) {
 console.log(`${x} + ${y} = ${parseInt(x) + parseInt(y)}`)
}

add( '4', '7' );



В результаье будет 11, как и в предыдущем примере.

То ест - сложение будет правильным.

Тегирование

Пожалуй, самой интересной особенностью шабблонных строг является тегирование, благодаря которому мы можем изменить вывод шаблонов при помощи функции.

Посмотрим на примере:

Простой вывод в консоль имени (переменной).


let name = "Bill";

console.log(`Hello ${name}`);



Результат:



А теперь я хочу, чтоб name всегда выводилась большими буквами.

Для этого я могу присвоить шаблону тег. Тегом будет название функции, которой я смогу обработать строку.

Для начала я создам функцию и назову её upperName(), первый аргумент которой будет содержать массив строковых литералов literals.

Второй и последующие аргументы содержат значения вычесленных выражений. Мы отправлем одно - name. Но если бы мы отправляли несколько, то

value1, value2, value3 и т.д.


function upperName(literals, value) {
 console.log(literals, value);
}



В том случае, когда мы не знаем сколько их будет, то в ES6 есть синтаксис оставшиеся параметры функции. Он предоставляет неогрмниченное множество аргументов в виде массива. Мы можем поставить три точки перед ...values. Теперь ...values будет массивом аргументов.

Пример:


function upperName(literals, ...values) {
 console.log(literals, value);
}



Для того, чтобы присвоить шаблону тег, я просто напишу название функции перед ним


let name = "Bill";

console.log(upperName`Hello ${name}`);

function upperName(literals, value) {
 console.log(literals, value)
}


Посмотрим в консоль:



В консоле мы увидим массив, в котором содержатся строки из которых состоит шаблон и значение переменной name.

Функция должна возвращать строку, но до этого мы можем сделать с ней все что угодно.

Как я и хтел я сделаю так, чтобы имя отображалось заглавными буквами.


let name = "Bill";

console.log(upperName`Hello ${name}`);

function upperName(literals, value) {
 return literals[0] + value.toUpperCase();
}



То есть, мы взяли первый литерал - Hello и прибавили к нему значение value, в кторм сделали все буквы заглавными - .toUpperCase().



Так мы сделали все буквы в переменной name заглавными.

В JavaScript, который работает нпрямую с HTML-шаблоном, шаблонные строки открывают массу дополнительных возможностей!



                                                                                                                                                             

пятница, 7 сентября 2018 г.

ES6 Spread Operator-оператор разворота (IV).

Оператор разворота (spread operator).





Все материалы по ES6


Оператор разворота или распространения - spread operator выглядит как три точки ...

Он позволяет разворачивать элементы массива для передачи их в качестве аргументов функции, или в элементы другого массива.

Лучше всего это объяснить на примере.



У нас есть два массива и мы хотим перенести элементы первого массива во воторй. Для этого мы можем использовать оператор разворота, который развернет первый массив ...arr1 и вставит их во второй - см. картинку выше.

Тепреь представьте, что у нас есть некий массив из трех элементов. И есть функция, которая принимает именно три аргумента.



Сам массив отправить в функцию мы не можем. но мы можем развернуть массив в аргументы функции используя оператор разворота.

doSomething(...arr1);





Теперь попробуем применить оператор разворота на практике.



Первое что мы сделаем это запустим скрипт Babel, который будет следить за файлами, и при их изменении создавать свежие версии.

Откроем папку проекта в командной строке (КС). Вводим команду:

npm run watch


И нажимаем Enter

В папке src создадим файл spread.js и сразу укажим его в файле index.html

<script src="src/spread.js"></script>

Использование в массивах.

В файле мы создадим три массива.


let pet = ['dog', 'cat', 'hamster'];
let wild_animals = ['tiger', 'bear', 'wolf'];

let animals = ['whale', 'elephant'];



Первый массив - домашние животные, второй массив - дикие животные и третий массив - просто животные.

Теперь мы хотим добавить первые два массива в один общий массив - животные (animals).

Попробуем вариант - просто вставить переменные первых двух массивов в третий напрямую:


let pet = ['dog', 'cat', 'hamster'];
let wild_animals = ['tiger', 'bear', 'wolf'];

let animals = [pet, 'whale', wildanimals, 'elephant'];

console.log(animals);





Обратите внимание, что получилось.

Не то что мы хотели!

Получился в итоге многомерный массив, который содержит добавленные элементы в виде отдельных массивов.

Для получения желаемого результата, мы можем воспользоваться оператором разворота - spread operator - (...)

Все что нужно сделать - это поставить три точки перед переменными в массиве


let pet = ['dog', 'cat', 'hamster'];
let wild_animals = ['tiger', 'bear', 'wolf'];

let animals = [...pet, 'whale', ...wild_animals, 'elephant'];

console.log(animals);





Теперь массив animals содержит всех животных, и домашних, и диких.

Если посмотреть на транпилированный код в файле dist/spread.js


'use strict';

var pet = ['dog', 'cat', 'hamster'];
var wild_animals = ['tiger', 'bear', 'wolf'];

var animals = [].concat(pet, ['whale'], wild_animals, ['elephant']);

console.log(animals);



Как можно видеть, здесь используется метод.concat на пустом массиве[] и соединяем все массивы по порядку.

Это не самое элегантное решение!

Намного проще поставить три точки!

Использование в функциях.

Будем использовать оператор разворота для передачи аргументов в функцию. Создадим функцию, которая сложит три числа и выведет результат в консоле браузера.


function add(x, y, z) {
 console.log(x + y + z);
};

let num = [1, 2, 3];



И массив num, состоящий из трех элементов.

Функция add принимает три аргумента и явно будет работать неправильно, если мы передадим ей в качестве аргумента весь массив.

Если сделать просто так add(num);



Как и ожидалось.

Теперь давайте попробуем передать массив, как аргументы в функцию, при помощи оператора spread

add(...num);


function add(x, y, z) {
 console.log(x + y + z);
};

let num = [1, 2, 3];

add(...num);





Оператор разворота- это очень удобный инструмент для работы с массивами!

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



                                                                                                                                                             


Хотите освоить самые современные методы написания React приложений? Надоели простые проекты? Нужны курсы, книги, руководства, индивидуальные занятия по React и не только? Хотите стать разработчиком полного цикла, освоить стек MERN, или вы только начинаете свой путь в программировании, и не знаете с чего начать, то пишите через форму связи, подписывайтесь на мой канал в Телеге, вступайте в группу на Facebook.Пишите мне - kolesnikovy70 почта gmail.com