Если вы еще не работали с JavaScript или работали с предыдущими версиями JavaScript, есть большая вероятность, что вы не изучили новые функции и синтаксис, добавленные в JavaScript ES6. Вы можете знать ES6 по ECMASCRIPT 6 или ES2015, но все они одинаковы.
В этом посте мы рассмотрим новые функции и синтаксис, предоставляемые ES6.
Оглавление
- Занятия
- Пусть и константа
- Стрелочные функции
- Деструктуризация
- Расширенные литералы объектов
- Шаблонные литералы
- Итераторы
- Обещания
Занятия
Классы не новы в JavaScript, они давно стали частью JavaScript. ES6 представляет новый способ написания классов.
Вот пример традиционного функционального класса:
function Starks(name) { this.name = name; this.houseName = 'House Stark'; this.seat = 'Winterfell'; } Starks.prototype.getHouseName = function() { return this.houseName; } var starks = new Starks(); console.log('Seat: ' + starks.seat); // Seat: Winterfell console.log('House: ' + starks.getHouseName()); // House: House Stark
При использовании ES6 мы можем использовать ключевое слово class для создания класса:
class Starks { constructor(name) { this.name = name; this.houseName = 'House Stark'; this.seat = 'Winterfell'; } getHouseName() { return this.houseName; } } const starks = new Starks(); console.log('Seat: ' + starks.seat); // Seat: Winterfell console.log('House: ' + starks.getHouseName()); // House: House Stark
Мы также можем создавать статические методы для классов с ключевым словом static.
class Starks { static words() { return 'Winter is coming!'; } } console.log(Starks.words()); // 'Winter is coming!'
Мы также можем расширить классы, используя ключевое слово extend
class Jon extends Starks { getHouseName() { return 'House Targaryen'; } } const jon = new Jon(); console.log(jon.getHouseName()); // House Targaryen
Пусть и константа
let
и const
— два новых ключевых слова для объявления переменных в ES6. В отличие от var
, let
и const
заблокированы в области действия, а не в области действия функции.
Не понял? Позволь мне объяснить:
function foo() {
if (true) {
var functionScoped = "I'm function scoped";
let blockScoped = "I'm block scoped"; // Same applies to const
}
console.log(functionScoped);
// I'm function scoped
console.log(blockScoped);
// Uncaught ReferenceError: blockScoped is not defined
}
foo();
Здесь к переменной functionScoped
можно получить доступ за пределами блока if, поскольку var
имеет область действия функции, поэтому переменная functionScoped
может использоваться во всей функции foo
. В то время как переменная blockScoped
доступна только в объявленном блоке, переменная blockedScoped
может использоваться только в блоке if.
Итак, мы получили разницу между var
и let
и const
, но в чем разница между let
и const
? Хотите знать, почему для объявления переменных используются два ключевых слова?
Тогда давайте к этому:
Разница между let
и const
заключается в том, что если переменная собирается изменить свое значение и собирается переназначить значение, используйте let
иначе const
. Значение должно быть указано во время объявления переменной const
. Если вы попытаетесь переназначить значение переменной const
, будет выброшена ошибка (Uncaught TypeError: Assignment для постоянной переменной).
Пример:
const PI = 3.14; // const is used here as value of PI is never going to change const r = 5; // Assuming value of r will be set dynamically let area = 0; // Reassigning the let variable as r is a positive value if (r > 0) area = PI * r * r; console.log('Area: '+ area);
Есть некоторые неправильные представления об использовании const для объектных переменных, поскольку мы думаем, что не можем изменить значение переменной const
, но следующий пример не вызовет ошибку.
const dob = {}; dob.date = 30; dob.month = 8;
Здесь мы не переназначаем значение константной переменной dob, мы добавляем свойство к константной переменной dob, которая не переназначается и, следовательно, не вызывает ошибки.
Стрелочные функции
Стрелочные функции также известны как толстые функции или лямбда-функции.
Стрелочные функции вводят новый синтаксис для написания функций и всегда анонимны, что означает, что мы не можем определить именованную стрелочную функцию, но мы можем назначить стрелочные функции переменным let и const, чтобы дать им ссылку.
function square(num) { return num * num; } // here (num) is the argument of the function // and => specifies the starting of function body. const square = (num) => { return num * num; } // Note that if a function has only one argument, () can be avoided. const square = num => { return num * num; } // Note that if a function body has only one statement // that returns a value, we can use shorthand like this. const square = num => num * num; // All of the functions declaration above // will produce same output. // Some other sugar syntax for arrow functions // A function without an argument must have () // Same applies to functions without an argument and function body const foo = () => 'bar'; // Returning an object from arrow shorthand // The return object is wrapped in () as {} means function body. const foo = () => ({ foo: 'bar' });
Стрелочные функции имеют лексический this
. что такое лексическое this
? Вы могли заметить такой код: var self = this;
или var that = this;
. Теперь мы можем избежать этого, используя стрелочные функции.
// ES5 this.nums = [1,2,3,4,5,6,7,8,9]; this.odds = []; var that = this; // ES5 way 1 this.nums.forEach(function (num) { if (num % 2 || num === 1) that.odds.push(num); }); // ES5 way 2 this.nums.forEach(function (num) { if (num % 2 || num === 1) this.odds.push(num); }, this); // ES5 way 3 this.nums.forEach(function (num) { if (num % 2 || num === 1) this.odds.push(num); }.bind(this)); console.log('Odds: ' + this.odds); // ES6 this.nums = [1,2,3,4,5,6,7,8,9]; this.odds = []; this.nums.forEach((num) => { if (num % 2 || num === 1) this.odds.push(num); }); console.log('Odds: ' + this.odds);
В способах 2 и 3 ES5 мы видим, что использовали это вместо того, так в чем же преимущество использования стрелочных функций по сравнению с привязкой this к функции? Привязка this к функции — медленная операция, и, привязывая this
к функции, мы выполняем привязку каждый раз, когда эта функция вызывается. Это означает, что это влияет на производительность и может быть решено с помощью стрелочных функций. Родительская область this передается стрелочным функциям, которые мы называем лексическими this.
Деструктурирование
Деструктуризация помогает нам извлекать вложенные данные из массивов или объектов.
const starks = [{ name: 'Arya' }, { name: 'Jon' }, { name: 'Sansa' }]; // Destructuring of array const [arya, jon, sansa] = starks; // I love Arya and I only want her from starks then const [arya] = starks; // Well arya wants her sister Sansa but not Jon then, const [arya, , sansa] = starks; // Skip a index by keeping it blank console.log(arya); // { name: 'Arya' } // Destructuring of object const { name } = arya; console.log(name); // Arya // Aliasing a property // (just in case we already have a variable named `'name'`) const { name: aryaName } = arya; console.log(aryaName); // Arya // Accessing nested values const res = { data: { records: [1, 2] } }; const { data: { records } } = res; console.log(records); // [1, 2]
Расширенные литералы объектов
Расширенные литералы объектов, такие как сокращения значений свойств, вычисляемые ключи свойств и сокращения методов.
Вот пример сокращенного значения свойства:
// ES5 var data = [{ something: 'Important' }]; return { data: data}; // ES6 const data = [{ something: 'Important' }]; // Here { data } is same as { data: data } return { data };
Вот пример вычисляемых ключей свойств:
// ES5
var name = 'Arya';
var starks = {};
starks['' + name] = { house: 'Stark', ability: 'many-faced gods' };
console.log(starks);
// { Arya: { house: 'Stark', ability: 'many-faced gods' } }
// ES6
const name = 'Arya';
const starks = { [name]: { house: 'Stark', ability: 'many-faced gods' } };
console.log(starks);
// { Arya: { house: 'Stark', ability: 'many-faced gods' } }
Мы уже использовали сокращение метода в классе. Вот еще один пример:
// ES5
var calculations = {
square: function(num) {
return num * num;
}
}
// ES6
const calculations = {
// No : function
square(num) {
return num * num;
}
}
Шаблонные литералы
Литералы шаблонов — это строковые литералы, которые позволяют использовать встроенные выражения. Эти выражения могут быть чем угодно, что может иметь вычисляемое значение.
В то время как строки заключаются в одинарные или двойные кавычки, литералы шаблонов заключаются в обратные кавычки (``). Литералы шаблонов могут иметь заполнители. Заполнители обозначаются знаком доллара, за которым следуют фигурные скобки ${expression}
.
Некоторые примеры:
console.log(`This is plain string`); const a = 5, b = 10; console.log('The number is ' + a + '.'); // The number is 5. console.log(`The number is ${a}.`); // The number is 5. console.log('The addition of a and b is ' + (a + b) + '.'); // The number is 15.
// Simple expression console.log(`The addition of a and b is ${a + b}.`); // The number is 15. function add(a, b) { return a + b; } // Calling a function console.log(`The addition of a and b is ${add(a, b)}.`); // The number is 15. // Using ternary operator. console.log(`The addition of the numbers a and b is ${add(a, b) % 2 === 0 ? 'even' : 'odd'}.`); // Multi line // Without template literals console.log('Text from line 1\n' + 'Text from line 2'); // Text from line 1 // Text from line 2 // With template literals console.log(`Text from line 1 Text from line 2`); // Text from line 1 // Text from line 2
Итераторы
ES6 предоставляет множество встроенных функций для перебора массивов. Эти функции работают быстро и позволяют избежать потенциальных ошибок или ошибок. Не используйте цикл для перебора массива, например for-of, for
и т. д.
Используйте
map()
/every()
/filter()
/find()
/findIndex()
/reduce()
/some()
/ … для перебора массивов иObject.keys()
/Object.values()
/Object.entries()
для создания массивов, чтобы можно было перебирать объекты.
Документацию по вышеуказанным методам можно найти на mozilla.
Некоторые примеры:
const numbers = [1, 2, 3, 4, 5]; let sum = 0; numbers.forEach((num) => { sum += num; }); // sum = 15; // Make use of the methods to improve code const sum = numbers.reduce((total, num) => total + num, 0); // sum = 15; const
increasedNumbers = numbers.map(num => num + 1); //
increasedNumbers = [2, 3, 4, 5, 6];
Обещания
ES6 предлагает встроенные обещания в JavaScript. Многие из вас знают об обетованиях и о том, почему они возникают.
Мы не будем углубляться в сами промисы, а продемонстрируем примеры промисов:
// A function that returns a promise after some time
// Without a promise constructor
function asyncExample(waitTime = 3000) {
return setTimeout(() => Promise.resolve(), waitTime);
}
// With promise constructor
function asyncExample(waitTime = 3000) {
// Prototype
// <Promise>(resolve, reject)
return new Promise((resolve) => setTimeout(resolve, waitTime));
}
asyncExample(5000).then(() => console.log('Will be logged after 5 secs.'));
Для обещаний есть чему поучиться, и, к счастью, у Mozilla действительно хорошая документация.