Translate

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

понедельник, 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);





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

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



                                                                                                                                                             

четверг, 6 сентября 2018 г.

ES6. Постоянная const. Отличия от let и var(III)

Использование const





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


Помимо var и let мы можем использовать для объявления переменных ключевое слово - const.

const - constant - постоянная. Позволяет объявить постоянные значения, которые нельзя изменить в ходе программы.

Давайте попробуем применить const!

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

Для этого нам следует открыть папку проекта в КС (командной строке) и ввести команду:

npm run watch


и нажать Enter

Скрипт запустится и теперь Babel будет следить за файлами.

Генерированные файлы нас будут интересовать только в порядке ознакомления, так как современные версии браузеров поддерживают const без транспиляции.

В папке src я создал файл const.js.

В этом файле мы создадим постоянную PI использую const.

Выводим значение PI в консоле.

const PI = 3.14159;

console.log(PI);


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

Тепреь важно изменить путь к файлу в файле index.html

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

Сохраняем и открываем в браузере.

И в консоле мы увидим значение PI.



Если мы посомтрим на то, что сгенерировал Babel, то мы увидим:

"use strict";

var PI = 3.14159;

console.log(PI);


Как вы видите. он просто заменил const на var.

Как я уже говорил, если бы мы даже использовали нетранспилированный файл с const, то никаких ошибок мы бы не увидили!

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


Если этого не сделать, то произойдет ошибка.

Давайте посмотрим. Стоит только убрать значение у PI и произойдет ошибка



-Переменой не присвоено значение!-

Теперь, вернем значение и попробуем его изменить ниже.


const PI = 3.14159;
PI = 3.15;
console.log(PI);



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

Теперь мы увидим другую ошибку



-Нельзя присвоить переменной иное значение. -

Постоянная, как и преременная объявленная через let не поднимаются.


То естсь нельзя использовать постоянную до её объявления!

Для примере перенесем вывод переменной до объявления константы:


console.log(PI);
const PI = 3.14159;



Мы получим ошибку.



- PI не объявлена -

Еще одна интересная особенность постоянных это то, что хотя мы и не можем поменять их значение, мы можем изменить значение свойства объекта, если он был объявлен при помощи const


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

Давайте посмотрим на примере.


const CAT = {
 COLOR: 'black'
};
console.log(CAT.COLOR);





Теперь мы изменим значение COLOR на white

const CAT = {
 COLOR: 'black'
};

CAT.COLOR = 'white';
console.log(CAT.COLOR);




И мы видим, что значение легко изменилось!

Нам это удалось. потому что мы изменили свойства объекта, а не саму постоянную!

При попытке изменить сам объект чаще всего происходит ошибка. В последних версиях - просто выдает настоящие значения - значения заданные при инициализации обьекта.

Например:


const CAT = {
 COLOR: 'black'
};

СAT = {
 COLOR: 'white'
};
console.log(CAT.COLOR);



Просто покажет в консоле black

Что использовать const, let или var ?

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

В остальных случаях используйте let.

Есть мнение. что по умолчанию следует использовать const и только для значений, которые изменятся - let.

А что с var? К сожалению, при написании кода на ES6 в нем нет необходимости.



                                                                                                                                                             

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

ES6. Переменная let. Области видимости и хостинг. (II)

Переменная let.





Сейчас пришло время более подробно познакомиться с переменной let и ее важнейшими отличиями от var.

Лучше всего это сделать на примерах.

В папке src в файле let.js запишем следующий код:


       if ( true ) {
         var temp = "ES5";
       }
       console.log(temp);



Запустим скрипт для транспиляции нашего кода. Если вы не помните настроек, то стоит посмотреть пост:ES6 подготовка к работе.

npm run watch


В папке dist появится файл let.jsсо следующим содержимым:

    "use strict";

    if (true) {
      var temp = "ES5";
    }
    console.log(temp);



Он ничем не отличается от исходного, кроме добавления "use strict".

Тпереь в файле index.html в теге script добавим путь к файлу let.js из папки dist.


     <script src="dist/let.js"></script>



Сохраняем и открываем файл в браузере. Откроем консоль и увидим:



Теперь, если мы поменяем var на let в папке src, то мы увидим следующее сообщение в консоле:



Это говорит о том. что наша переменная необъявлена!

Это произошло потому, что

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


В этом легко убедиться если посмотреть в папку dist/let.js:


    "use strict";

    if (true) {
     var _temp = "ES5";
    }
    console.log(temp);



У нас появилась переменная _temp, а в консоле выводится temp (без нижнего подчеркивания).

Хостинг - подьем переменных

Переменная объявленная с помощью let не поднимается и поэтому их нельзя использовать до их объявления!


Пример:

В файле index.html подключим исходный код из файла src/let.js.


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



А в самом этом файле вызовем переменную до ее объявления:


     console.log(temp);
     let temp = "ES5";



Сохраним и посмотрим на консоль.



Там будет ошибка, потому что наша переменная не объявлена!

То есть мы не можем использовать переменную объявленную с помощью let до её объявления!

Если поменять let на var, то мы увидим:



Ошибки не будет. Будет undefined

Мы видим undefined потому, что перед тем как выполнить код, движок JS поднял переменную temp наверх и присвоил ей значение undefined, после чего мы вывели значение в консоль, и только после этого, присвоили переменной temp значение ES5

Это выглядит вот так:


    var temp, //undefined 
    console.log(temp);
    var temp = "ES5";



Рассмотрим применение let на практике.

Создадим пять кнопок в файле index.html

src/let.js Все удалим и объявим переменную buttons и поместим в нее все кнопки:

var buttons = document.querySelectorAll('button');

Далее простой цикл for внутри которого мы объявили переменную button и присваеваем ей все кнопки по порядку. А в качестве текcта кнопки будет значение i

button.innerText = i;

При нажатии на кнопку я хочу, чтобы в консоле отобразился её порядок:

  
     button.onclick = function(e) {
           console.log(i); 
      };

Файл let полностью:

    var buttons = document.querySelectorAll('button');

    for (var i = 0; i < buttons.length; i++) {
        var button = buttons[i];
        button.innerText = i;
        button.onclick = function(e) {
           console.log(i); 
        };
    }



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



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

В C# или Java аналогичный код работал бы правильно.

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

Это тоже самое. что записать наш код так:


    var buttons = document.querySelectorAll('button');
    var i;
    for ( i = 0; i < buttons.length; i++) {
        var button = buttons[i];
        button.innerText = i;
        button.onclick = function(e) {
           console.log(i); 
        };
    }



Теперь ВСЕ функции видят одну и тужe i.

Так работают замыкания в JavaScript!

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

Для этого мы используем let!

Меняем var на let и проблема решена!



Файл src/let.js


    var buttons = document.querySelectorAll('button');

    for (let i = 0; i < buttons.length; i++) {
        var button = buttons[i];
        button.innerText = i;
        button.onclick = function(e) {
           console.log(i); 
        };
    }



Из этого можно сделать вывод, что let делает работу с переменными более понятной и интуитивной. Особенно для людей с опытом работы в других языках.

                                                                                                                                                             

ES6 подготовка к работе.

Установка и настройка Babel.





Для работы с ES6 нам нужно установить Babel и сделать некоторые настройки.

Для этого нужно установить последнюю стабильную версию Node.js и NPM.

Если у вас они не установлены, то вы сможете сделать это с официальных сайтов, перейдя по ссылкам выше.

Установка очень простая и я на ней останавливаться не буду.

После установки Node.js вы сможете проверить версию набрав в КС (командная строка - здесь и далее)

node -v


npm -v
- для версии NPM.

Создадим рабочую папку из КС - в нужной директории

mkdir Имя_Папки_проекта


Для перехода в папку (директорию).

cd Имя_папки_(или_директории)


Или можно просто перетащить нужную папку прямо в КС и нажать Enter, таким образом получить путь и перейти к нужной папке.

Переходим в созаную папку.

Теперь нам нужно инициализировать NPM.

В КС набираем:

npm init -y


В нашем случае -y обозначает, что мы принимаем все параметры по умолчанию (Yes).

В папке вашего проекта после этого появится файл package.json В этом файле содержится информация необходимая для работы NPM.

Вернемся к Babel



Babel предназначен для траспиляции кода. Транспиляция - это перевод кода с одного языка на другой. В нашем случае с ES6 на ES5. После этого мы сможем использовать код в любом современном браузере.

Babel можно использовать с другими инструментами и фреймворками. На сайте Babel есть подробная инструкция.

Пройдя по этой ссылке Using Babel мы сможем с вами выбрать нужную нам конфигурацию. Так как у нас есть Node.js, NPM и мы собираемся использовать CLI , то наша команда сформируется так

npm install babel-cli babel-core babel-preset-es2015 --save-dev


cli - comande line interface Интерфейс командной строки - позволит использовать команду babel в самой КС, как NPM.

babel-core - основой модуль Babel.

babel-preset-es2015 - модуль еобходимый для транспиляции ES6.

--save-dev добавит модули в package.json в раздел devDependencies, в которм указываются модули необходимые для разработки.

После установки в папке проекта появится папка node_modules.

В этой папке содержатся папки модулей, которые мы устаовили. Также эти модули добавились в наш файл package.json в раздел devDependencies.

В папке проекта создадим папку src Source-Источник - для исходного кода. и папку dist Distribution -распространиение.- конечный код.

index.html - (так же в корне папки проекта) файл с помощью которого мы будем проверять работоспособность кода.

В этом файле обычная разметка с тегом script


<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
 <script></script>
</body>
</html>



Проверить Babel

В папке src создадим файл script.js.

Внутри файла мы попробуем одно из нововедений ES6


    let variable = "Item";



let - ключевое слово, которе позволяет объявлять локальные переменные.

Теперь нам нужно перевести (транспилировать) ES6 в ES5.

Для этого в файле package.json в разделе scripts удаляем скрпт-тест ("test": "echo \"Error: no test specified\" && exit 1") вставим следующее -

"build": "babel src -d dist --presets es2015"

Это мы написали скрипт, который будет брасть исходный код из папки src. -d - указывает куда поместить измененный код - dist.

--presets es2015 - указывает что мы транспилируем код ES 6.

Сохраняем

В КС

npm run build


Этой командой мы можем запускать скрипты, которые мы указываем в файле package.json

Нажимаем Enter Запустится скрипт и когда он завершится в папке dist

Появится файл script.js вот с таким содержимым:


    "use strict";

    var variable = "Item";



Как вы видете слово let заменено на var и значит все транспилировалось и можно использовать код на странице.

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

npm run build


Мы добавим еще один скрипт в файл package.json

"watch": "babel src -d dist --presets es2015 -w"

-w означает, что теперь Babel будет смотрет за файлами в папке src. И как тоько будут изменения в файлах или вообще в папке src (например - создание нового файла) то тут же все автоматически отразится уже готовым кодом в папке dist.

package.json
{
  "name": "ES-6-new",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "babel src -d dist --presets es2015",
    "watch": "babel src -d dist --presets es2015 -w"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.3",
    "babel-preset-es2015": "^6.24.1"
  }
}



Здесь файл package.json полностью с выделенными красным цветом изменениями.

Теперь запускаем команду в КС:

npm run watch


И теперь запишем в наш файл script.js в папке src

let say = "Hello";

Сохраним.

И в файле script.js в папке dist отразятся наши изменения:

var say = "Hello";

Остановить слежение - Ctrl + C и Y если остановить или N - если продолжить.

См картинку ниже:



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

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


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