Советы по ES6, чтобы сделать ваш код короче, чище и читабельнее
напишите перед статьей
Эта статья переведена сES6 tips and tricks to make your code cleaner, shorter, and easier to read!В статье резюмируется es6 с точки зрения чистоты кода. Пожалуйста, укажите на ошибки.
шаблонные литералы шаблонные строки
Строки-шаблоны делают работу со строками проще, чем когда-либо, они начинаются с обратной кавычки (`) и могут использоваться с${变量}
для вставки переменных. Давайте сравним следующие две строки кода.
var fName = 'Peter', sName = 'Smith', age = 43, job= 'photographer';
var a = 'Hi, I\'m ' + fName + ' ' + sName + ', I\'m ' + age + ' and work as a ' + job + '.';
var b = `Hi, I'm ${ fName } ${ sName }, I'm ${ age } and work as a ${ job }.`;
Все красиво не правда ли, код читабельнее не правда ли? В фигурные скобки можно поместить что угодно: переменные, уравнения или вызовы функций. Я буду использовать эти методы в примерах на протяжении всей статьи.
синтаксис области блока
JavaScript использует область действия функции, поэтому мы все чаще используем выражения анонимных непосредственных функций (iife) для инкапсуляции целых файлов JavaScript. Мы делаем это, чтобы изолировать все переменные в файле, чтобы избежать конфликтов переменных.
Теперь у нас есть объявления переменных с блочной областью видимости и два совершенно новых объявления переменных с блочной областью видимости.
let
команда объявления let
Эта команда очень похожа на var, но существенно отличается. Так как это блочная область, объявление новой переменной с тем же именем вообще не влияет на внешние переменные.
var a = 'car' ;
{
let a = 5;
console.log(a) // 5
}
console.log(a) // car
Поскольку он ограничен областью действия на уровне блоков, он решил очень классический вопрос интервью: «Каков вывод следующего кода и как я могу изменить его, чтобы он выглядел так, как вы хотите, чтобы он выполнялся?»
for (var i = 1; i < 5; i++){
setTimeout(() => { console.log(i); }, 1000);
}
В этом примере вывод «5 5 5 5 5», потому что переменнаяi
изменения в каждой итерации.
если мы положимvar
сталиlet
, все изменилось. Теперь каждый цикл будет создавать новую область на уровне блока, чтобы ограничить i текущим циклом, который можно понять следующим образом:
{let i = 1; setTimeout(() => { console.log(i) }, 1000)}
{let i = 2; setTimeout(() => { console.log(i) }, 1000)}
{let i = 3; setTimeout(() => { console.log(i) }, 1000)}
{let i = 4; setTimeout(() => { console.log(i) }, 1000)}
{let i = 5; setTimeout(() => { console.log(i) }, 1000)}
var
а такжеlet
Еще одно отличиеlet
не какvar
то же, что продвигается переменной
{
console.log(a); // undefined
console.log(b); // ReferenceError
var a = 'car';
let b = 5;
}
Из-за его более ограниченной области применения и более предсказуемого поведения некоторые люди даже считают, что вам следует использоватьlet
заменитьvar
, если вам действительно не нужен подъем переменных или более расслабленная область видимости, тогда вы используетеvar
Const
В прошлом, если вы хотели объявить константу в JavaScript, было принято называть ее в верхнем регистре. Однако на самом деле это не защищает переменную от изменения — это просто позволяет другим разработчикам знать, что это константа и ее не следует изменять.
теперь у нас естьconst
Заказ.
const
Не делая переменную полностью неизменную, просто блокируя его назначение, когда у вас есть сложная переменная (массив или объект), значение все еще может быть изменено.
{
const d = [1, 2, 3, 4];
const dave = { name: 'David Jones', age: 32};
d.push(5);
dave.job = "salesman";
console.log(d); // [1, 2, 3, 4, 5]
console.log(dave); // { age: 32, job: "salesman", name: 'David Jones'}
}
Проблема с функциями определения области видимости блока
Объявления функций также могут быть ограничены областью действия на уровне блоков.
{
bar(); // works
function bar() { /* do something */ }
}
bar(); // doesn't work
но когда вы находитесь вif
Проблема возникает, когда функция объявлена в операторе.
Рассмотрим эту ситуацию:
if ( something) {
function baz() { console.log('I passed') }
} else {
function baz() { console.log('I didn\'t pass') }
}
baz();
До ES6 оба объявления функций были подняты переменными, и результат должен бытьI didn't pass
что бы ни было в состоянии. но теперь мы получим выводReferenceError
, потому чтоbaz
Всегда ограничивается областью действия на уровне блоков.
Оператор спреда
Представлен ES6...
оператор, этот оператор относится к «оператору спреда». У него два основных применения: 1. Поместить массив или объект в новый массив или объект 2. Объединить несколько параметров в массиве вместе
Первое использование, вероятно, будет тем, которое вы будете использовать чаще всего. Итак, давайте сначала посмотрим на него.
let a = [3, 4, 5];
let b = [1, 2, ...a, 6];
console.log(b); // [1, 2, 3, 4, 5, 6]
Оператор распространения очень полезен, если мы хотим передать набор параметров в массив функции.
function foo(a, b, c) {
console.log(`a=${a}, b=${b}, c=${c}`)
}
let data = [5, 15, 2];
foo( ...data); // a=5, b=15, c=2
Объект также может быть расширен, что записывает каждую пару ключ-значение в новый объект. (Расширения объектов уже находятся на четвертом этапе предложения и будут официально доступны в es2018. Но в настоящее время эта функция поддерживается только в Chrome 60 и более поздних версиях, Firefox 55 и более поздних версиях и Node 6.4.0 и более поздних версиях.) Примечание. вes2018 в блоге 2alityВ статье мы узнали, что на только что завершившейся конференции TC39 были доработаны характеристики ECMA2018. 】
let car = { type: 'vehicle ', wheels: 4};
let fordGt = { make: 'Ford', ...car, model: 'GT'};
console.log(fordGt); // {make: 'Ford', model: 'GT', type: 'vehicle', wheels: 4}
Еще одна особенность оператора спреда заключается в том, что он может генерироватьновый массив или объектВ следующем примере b — это только что созданный массив, а c просто ссылается на тот же массив.
let a = [1, 2, 3];
let b = [ ...a ];
let c = a;
b.push(4);
console.log(a); // [1, 2, 3]
console.log(b); // [1, 2, 3, 4] 不同的数组
c.push(5);
console.log(a); // [1, 2, 3, 5]
console.log(c); // [1, 2, 3, 5] 同一个数组
Второе использование — объединение переменных в массив. Этот метод может быть очень полезен, когда вы не знаете, сколько параметров имеет функция.
function foo(...args) {
console.log(args);
}
foo( 'car', 54, 'tree'); // [ 'car', 54, 'tree' ]
Параметр по умолчанию Значение параметра по умолчанию
Функции теперь могут быть определены со значениями параметров по умолчанию. Никакие параметры или неопределенные значения не инициализируются значениями по умолчанию. Но следует отметить, что и null, и false будут сведены к 0.
function foo( a = 5, b = 10) {
console.log( a + b);
}
foo(); // 15
foo( 7, 12 ); // 19
foo( undefined, 8 ); // 13
foo( 8 ); // 18
foo( null ); // 10 as null is coerced to 0
Тип значения по умолчанию может быть больше, чем просто тип значения — это также может быть выражение или функция.
function foo( a ) { return a * 4; }
function bar( x = 2, y = x + 4, z = foo(x)) {
console.log([ x, y, z ]);
}
bar(); // [ 2, 6, 8 ]
bar( 1, 2, 3 ); //[ 1, 2, 3 ]
bar( 10, undefined, 3 ); // [ 10, 14, 3 ]
Разрушение
Деструктуризация — это процесс разделения массива или объекта слева от знака равенства. Этот массив или объект может быть получен из переменной, функции или уравнения.
let [ a, b, c ] = [ 6, 2, 9];
console.log(`a=${a}, b=${b}, c=${c}`); //a=6, b=2, c=9
function foo() { return ['car', 'dog', 6 ]; }
let [ x, y, z ] = foo();
console.log(`x=${x}, y=${y}, z=${z}`); // x=car, y=dog, z=6
Структура типа объекта, ключи объекта могут быть перечислены в фигурных скобках для извлечения пар ключ-значение.
function bar() { return {a: 1, b: 2, c: 3}; }
let { a, c } = bar();
console.log(a); // 1
console.log(c); // 3
console.log(b); // undefined
Иногда вам может понадобиться извлечь значение и присвоить его новой переменной, что можно сделать, используя «ключ: переменная» слева от знака равенства.
function baz() {
return {
x: 'car',
y: 'London',
z: { name: 'John', age: 21}
};
}
let { x: vehicle, y: city, z: { name: driver } } = baz();
console.log(
`I'm going to ${city} with ${driver} in their ${vehicle}.`
); // I'm going to London with John in their car.
Кроме того, структура объекта позволяет присваивать несколько переменных.
let { x: first, x: second } = { x: 4 };
console.log( first, second ); // 4, 4
Краткое представление литералов и свойств объектов
Когда вы создаете литералы объектов из множества параметров, ES6 позволяет вам опустить ключ, если он имеет то же имя, что и переменная.
let a = 4, b = 7;
let c = { a: a, b: b };
let concise = { a, b };
console.log(c, concise) // {a: 4, b: 7}, {a: 4, b: 7}
Это также можно использовать с деструктурированием, чтобы сделать ваш код чище.
function foo() {
return {
name: 'Anna',
age: 56,
job: { company: 'Tesco', title: 'Manager' }
};
}
// pre ES6
let a = foo(), name = a.name, age = a.age, company = a.job.company;
// ES6 destructuring and concise parameters
let { name, age, job: {company}} = foo();
Краткая нотация также может использоваться для деструктуризации объекта и передачи его в функцию. Методы 1 и 2 — это то, как вы делали это до es6, а метод 3 — использовать деструктурирование и краткие выражения.
let person = {
name: 'Anna',
age: 56,
job: { company: 'Tesco', title: 'Manager' }
};
// method 1
function old1( person) {
var yearOfBirth = 2018 - person.age;
console.log( `${ person.name } works at ${ person.job.company } and was born in ${ yearOfBirth }.`);
}
// method 2
function old1( person) {
var age = person.age,
yearOfBirth = 2018 - age,
name = person.name,
company = person.job.company;
console.log( `${ name } works at ${ company } and was born in ${ yearOfBirth }.`);
}
// method 3
function es6({ age, name, job: {company}}) {
var yearOfBirth = 2018 - age;
console.log( `${ name } works at ${ company } and was born in ${ yearOfBirth }.`);
}
Используя ES6, мы можем извлечьage
,name
,а такжеcompany
, без каких-либо других объявлений переменных.
Имя динамического свойства
В ES6 добавлена возможность создавать или добавлять свойства с динамически назначаемыми ключами.
let city= 'sheffield_';
let a = {
[ city + 'population' ]: 350000
};
a[ city + 'county' ] = 'South Yorkshire';
console.log(a); // {sheffield_population: 350000, sheffield_county: 'South Yorkshire' }
стрелочная функция
Стрелочные функции имеют еще две важные особенности: их структуру и ихthis
направление
У них более простая структура, чем у традиционных функций, потому что они не требуют ключевых слов.function
И они могут автоматически возвращаться в ту часть, которая находится за стрелкой, независимо от того, что находится за стрелкой.
var foo = function( a, b ) {
return a * b;
}
let bar = ( a, b ) => a * b;
Если функция имеет более одного вычисления, ее можно заключить в фигурные скобки, и функция возвращает все, что возвращается в области блока.
Одно из наиболее важных применений стрелочных функций — в функциях, связанных с массивами, например.map
,.forEach
,.sort
и т.п.
let arr = [ 5, 6, 7, 8, 'a' ];
let b = arr.map( item => item + 3 );
console.log(b); // [ 8, 9, 10, 11, 'a3' ]
Имея более короткое выражение, стрелочные функции также устраняют распространенную проблему с таким поведением привязки. До ES6 решение этой проблемы обычно заключалось в использованииself
переменная для хранения этого указателя.
var clickController = {
doSomething: function (..) {
var self = this;
btn.addEventListener(
'click',
function() { self.doSomething(..) },
False
);
}
};
Это назначение должно быть выполнено, потому что привязка this является динамической. Это означает, что this внутри eventlistener не ссылается на то же самое внутри doSomething.
Внутри стрелочной функции привязка this является семантически текущей, а не динамической. Это также основная конструктивная особенность стрелочных функций.
Хотя эта лексика это здорово, иногда это не то, что мы хотим.
let a = {
oneThing: ( a ) => {
let b = a * 2;
this.otherThing(b);
},
otherThing: ( b ) => {....}
};
a.oneThing(6);
когда мы используемa.oneThing(6)
, этоthis.otherThing(6)
выдаст ошибку с ошибкой ссылки, потому чтоthis
нет указателя на объектa
, но указывает на область окружения. Если вы используете код ES6 с синтаксисом ES6, вам нужно знать об этом.
для... петель (для... петель)
ES6 добавил новый способ перебора каждого значения в массиве, этот способ такой же, как и существующие.for...in
Перебор индекса отличается.
let a = ['a', 'b', 'c', 'd' ];
// ES6
for ( var val of a ) {
console.log( val );
} // "a" "b" "c" "d"
// pre-ES6
for ( var idx in a ) {
console.log( idx );
} // 0 1 2 3
использовать новыйfor ... of
петли, внутри каждой петли сохраняетсяlet val = a[idx]
.
Массивы, строки, генераторы и коллекции в стандартном JavaScript поддерживают итерацию. Обычные объекты нельзя перебирать, как обычно, используя for...of, если только вы сами не определите итератор.
Числовые литералы
Код ES5 хорошо обрабатывает десятичные и шестнадцатеричные форматы чисел, но восьмеричный формат не указан. На самом деле восьмеричное запрещено в строгом режиме.
ES6 добавил новый формат, добавив o после начального 0, чтобы объявить восьмеричное число. В то же время в es6 также был добавлен бинарный формат.
Number( 29 ) // 29
Number( 035 ) // 35 in old octal form.
Number( 0o35 ) // 29 in new octal form
Number( 0x1d ) // 29 in hexadecimal
Number( 0b11101 ) // 29 in binary form
Более
ES6 также дает нам множество других способов сделать наш код чище, читабельнее и стабильнее. Моя цель — написать продолжение этой статьи, включив в него некоторые менее известные части ES6.
Если не терпится, прочтите Кайла Симпсона.YOU DONT KNOW JAVASCRIPT ON ES6, или взгляните на этоклассный маленький сайт