Эта статья включена в нашу книгу « JavaScript: лучшие практики» . Будьте в курсе быстро меняющихся лучших практик современного JavaScript.
Современный JavaScript быстро развивается для удовлетворения меняющихся потребностей новых сред и сред. Понимание того, как воспользоваться этими изменениями, поможет вам сэкономить время, улучшить навыки и заметить разницу между хорошим кодом и отличным кодом.
Знание того, что пытается сделать современный JavaScript, может помочь вам решить, когда использовать новый синтаксис с максимальной выгодой, и когда все еще имеет смысл использовать традиционные методы.
Что-то твердое, чтобы цепляться за
Я не знаю никого, кто не смущен состоянием JavaScript в наши дни, независимо от того, являетесь ли вы новичком в JavaScript или вы уже давно его программируете. Так много новых структур, так много изменений в языке и так много контекстов для рассмотрения. Удивительно, что кто-нибудь выполнил любую работу со всеми новыми вещами, которые мы должны изучать каждый месяц.
Я считаю, что секрет успеха любого языка программирования, независимо от того, насколько сложным является приложение, заключается в возвращении к основам. Если вы хотите разбираться в Rails, начните с работы над своими навыками Ruby, и если вы хотите использовать неизменяемые и однонаправленные потоки данных в изоморфном взаимодействии с веб-пакетом (или с тем, что делают крутые ботаники в наши дни), начните с знания вашего основного JavaScript.
Понимание того, как работает сам язык, гораздо более практично, чем знакомство с новейшими средами и средами. Они меняются быстрее, чем погода. А с JavaScript у нас есть длинная история вдумчивой информации онлайн о том, как JavaScript был создан и как его эффективно использовать.
Проблема в том, что некоторые из новых методов, появившихся в последних версиях JavaScript, делают некоторые из старых правил устаревшими. Но не все из них! Иногда новый синтаксис может заменить более грубый для выполнения той же задачи. В других случаях новый подход может показаться более простой заменой того, что мы привыкли делать, но есть небольшие различия, и важно знать, что это такое.
Ложка синтаксического сахара
Много изменений в JavaScript за последние годы были описаны как синтаксический сахар для существующего синтаксиса. Во многих случаях синтаксический сахар может помочь медицине в том, что Java-программисты научатся работать с JavaScript, а для всех остальных нам нужен просто более чистый и простой способ выполнить то, что мы уже знали. Другие изменения, кажется, вводят новые магические возможности.
Но если вы пытаетесь использовать современный синтаксис, чтобы воссоздать знакомую старую технику, или придерживаетесь ее, не понимая, как она на самом деле себя ведет, вы рискуете:
- необходимость отладки кода, который отлично работал раньше
- вводить тонкие ошибки, которые могут поймать вас во время выполнения
- создание кода, который молча терпит неудачу, когда вы меньше всего этого ожидаете.
Фактически, некоторые из изменений, которые кажутся заменами существующим методам, фактически ведут себя не так, как код, который они предположительно заменяют. Во многих случаях может иметь больше смысла использовать оригинальный, более старый стиль, чтобы выполнить то, что вы пытаетесь сделать. Признать, когда это происходит, и знать, как сделать выбор, очень важно для написания эффективного современного JavaScript.
Когда твой const
Современный JavaScript ввел два новых ключевых слова, let
const
var
Но они не ведут себя точно так же, как var
В традиционном JavaScript всегда было чистой практикой кодирования объявлять переменные с ключевым словом var
Невыполнение этого условия означало, что объявленные вами переменные могли быть доступны в глобальной области действия всеми сценариями, которые выполнялись в том же контексте. А поскольку традиционный JavaScript часто запускался на веб-страницах, где несколько скриптов могли загружаться одновременно, это означало, что переменные, объявленные в одном скрипте, могли просочиться в другой.
Позволяет использовать чистую замену var
Но let
let
Объявления переменных с var
области независимо от того, где они были размещены внутри этой области. Это означало, что даже глубоко вложенная переменная может считаться объявленной и доступной с самого начала ее содержащей области. То же самое не верно для var
let
const
Когда вы объявляете переменную с помощью console.log(usingVar); // undefined
var usingVar = "defined";
console.log(usingVar); // "defined"
console.log(usingLet); // error
let usingLet = «defined»; // never gets executed
console.log(usingLet); // never gets executed
let
Блок в JavaScript отличается набором фигурных скобок const
Это очень удобно для использования переменных в области блока, таких как итераторы и циклы. Ранее переменные, объявленные внутри циклов, были бы доступны для содержащей области, что могло бы привести к путанице, когда несколько счетчиков могли бы использовать одно и то же имя переменной. Однако {}
let
Другое альтернативное объявление — for (var count = 0; count < 5; count++) {
console.log(count);
} // outputs the numbers 0 - 4 to the console
console.log(count); // 5
for (let otherCount = 0; otherCount < 5; otherCount++) {
console.log(otherCount);
} // outputs the numbers 0 — 4 to the console
console.log(otherCount); // error, otherCount is undefined
Но это не совсем постоянно.
const
const
var
let
var x; // valid
let y; //valid
const z; // error
const
Но если вы ожидаете, что ваше const z = 3; // valid
z = 4; // error
const
const
По этой причине я скептически отношусь к тому, что люди рекомендуют постоянно использовать const z = []; // valid
z.push(1); // valid, and z is now [1]
z = [2] // error
const
Хотя рекомендуется использовать ваши переменные как неизменяемые, JavaScript не будет применять это для содержимого ссылочных переменных, таких как массивы и объекты, объявленные с помощью var
Поэтому ключевое слово const
Я склонен использовать const
В противном случае я использую const
В последнее время я не нашел необходимости использовать let
Ограничение сферы действия функции
Традиционные функции, определенные с помощью ключевого слова var
function
Их также можно использовать с ключевым словом function doSomething(param) {
return(`Did it: ${param}`);
}
console.log(doSomething("Hello")); // "Did it: Hello"
new
Функции, используемые любым из этих способов, могут быть определены до или после их вызова. Это не имеет значения для JavaScript.
function Animal(name) {
this.name = name;
}
let cat = new Animal("Fluffy");
console.log(`My cat's name is ${cat.name}.`); // "My cat's name is Fluffy."
Традиционная функция также создает свой собственный контекст, определяя значение для console.log(doSomething("Hello")); // "Did it: Hello"
let cat = new Animal(«Fluffy»);
console.log(`My cat’s name is ${cat.name}.`); // «My cat’s name is Fluffy.»
function doSomething(param) {
return(`Did it: ${param}`);
}
function Animal(name) {
this.name = name;
}
Любые операторы или подфункции, определенные в нем, выполняются и, необязательно, позволяют нам связать значение для this
Для ключевого слова это очень много, и обычно это больше, чем нужно программисту в любом месте. Поэтому современный JavaScript разделяет поведение традиционной функции на функции и классы стрелок.
Добраться в класс вовремя
Одна часть традиционной this
function
Это позволяет программистам выбирать, предпочитают ли они следовать более функциональной парадигме программирования с вызываемыми функциями стрелок или использовать более объектно-ориентированный подход с классами для замены прототипного наследования традиционных функций.
Классы в JavaScript выглядят и действуют как простые классы в других объектно-ориентированных языках и могут быть легкой ступенькой для разработчиков Java и C ++, стремящихся перейти на JavaScript по мере расширения JavaScript на сервер.
Одно из различий между функциями и классами при выполнении объектно-ориентированного программирования в JavaScript заключается в том, что классы в JavaScript требуют предварительного объявления, как в C ++ (хотя и не в Java). То есть class
class
Прототипное наследование с использованием ключевого слова new
function
function
class
Отмеченные различия с функциями стрелок
К другому аспекту традиционных функций теперь можно получить доступ, используя функции стрелок, новый синтаксис, который позволяет вам писать вызываемую функцию более кратко, чтобы более точно вписываться в обратный вызов. На самом деле, самый простой синтаксис для функции стрелки — это одна строка, которая полностью исключает фигурные скобки и автоматически возвращает результат выполненного оператора:
// Using a function to declare and instantiate an object (hoisted)
let aProto = new Proto("Myra");
aProto.greet(); // "Hi Myra"
function Proto(name) {
this.name = name;
this.greet = function() {
console.log(`Hi ${this.name}`);
};
};
// Using a class to declare and instantiate an object (not hoisted)
class Classy {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hi ${this.name}`);
}
};
let aClassy = new Classy("Sonja");
aClassy.greet(); // "Hi Sonja"
Функции стрелок заключают в себе несколько качеств, которые могут сделать их вызов более удобным, и исключают другое поведение, которое не так полезно при вызове функции. Они не являются заменой более универсального ключевого слова традиционной const traditional = function(data) {
return (`${data} from a traditional function`);
}
const arrow = data => `${data} from an arrow function`;
console.log(traditional(«Hi»)); // «Hi from a traditional function»
console.log(arrow(«Hi»)); // «Hi from an arrow function»
Например, функция стрелки наследует function
this
Это отлично подходит для ситуаций, таких как обработка событий или arguments
Традиционные функции вынуждают программистов писать замысловатый код, который привязывает функцию к существующему setTimeout
this
.bind(this)
Ничего из этого не нужно с помощью стрелок.
class GreeterTraditional {
constructor() {
this.name = "Joe";
}
greet() {
setTimeout(function () {
console.log(`Hello ${this.name}`);
}, 1000); // inner function has its own this with no name
}
}
let greeterTraditional = new GreeterTraditional();
greeterTraditional.greet(); // "Hello "
class GreeterBound {
constructor() {
this.name = "Steven";
}
greet() {
setTimeout(function () {
console.log(`Hello ${this.name}`);
}.bind(this), 1000); // passing this from the outside context
}
}
let greeterBound = new GreeterBound(); // "Hello Steven"
greeterBound.greet();
class GreeterArrow {
constructor() {
this.name = "Ravi";
}
greet() {
setTimeout(() => {
console.log(`Hello ${this.name}`);
}, 1000); // arrow function inherits this by default
}
}
let greeterArrow = new GreeterArrow();
greeterArrow.greet(); // "Hello Ravi"
Понять, что вы получаете
Это не просто синтаксический сахар. Много новых изменений в JavaScript было введено, потому что была необходима новая функциональность. Но это не значит, что старые причины традиционного синтаксиса JavaScript исчезли. Часто имеет смысл продолжать использовать традиционный синтаксис JavaScript, а иногда использование нового синтаксиса может значительно ускорить процесс написания и понимания кода.
Проверьте те онлайн-учебники, которые вы читаете. Если автор использует var
function
И это нормально. Сегодня мы можем многому научиться и применить из традиционных способов преподавания и использования JavaScript. Но если вы увидите let
const
Лучшая практика в современном JavaScript — обращать внимание на то, что на самом деле делает язык. В зависимости от того, к чему вы привыкли, это не всегда может быть очевидным. Но подумайте о том, что код, который вы пишете, пытается выполнить, где вам нужно будет его развернуть, и кто будет модифицировать его дальше. Затем решите для себя, какой будет наилучший подход.