JavaScript - это простой в освоении язык программирования. Легко писать программы, которые работают и что-то делают. Однако сложно написать чистый код JavaScript.
В этой статье мы рассмотрим, как реорганизовать наши функции JavaScript, чтобы они были понятными и удобными для чтения.
Рефакторинг конструкторов в классы
В JavaScript класс - это просто синтаксический сахар для функций-конструкторов, поэтому на самом деле они являются функциями.
Все классы обеспечивают более интуитивный синтаксис для функций конструктора, избегая работы с прототипами и используя call
для вызова функций родительского конструктора, когда мы расширяем другой конструктор.
Например, вместо написания:
function Foo(name) { this.name = name; } Foo.prototype.getName = function() { return this.name; }
Мы пишем:
class Foo { constructor(name) { this.name = name; } getName() { return this.name; } }
Как мы видим, с синтаксисом класса ясно, где находится конструктор и какие методы экземпляра содержит наш класс с синтаксисом класса.
Вместо того, чтобы прикреплять методы экземпляра к прототипу функции-конструктора, мы добавляем его в класс.
Кроме того, нам не нужно постоянно писать ключевое слово function
, что сокращает время набора и делает код более понятным. В этом синтаксисе нет двусмысленности.
Если мы хотим сделать наследование, вместо того, чтобы писать:
function Animal(name) { this.name = name; } Animal.prototype.getName = function() { return this.name; } function Cat(name) { Animal.call(this, name); } Cat.prototype.constructor = Animal;
Мы пишем:
class Animal { constructor(name) { this.name = name; } getName() { return this.name; } } class Cat extends Animal { constructor(name) { super(name); } }
Таким образом, мы получаем ошибку, если мы забыли вызвать родительский конструктор, чего мы не получаем, когда забыли вызвать родительский конструктор в примере функции конструктора.
Мы также проясняем, что мы расширяем класс Animal
с помощью ключевого слова extends
вместо того, чтобы самому устанавливать родительский конструктор в дочернем конструкторе.
По возможности избегайте традиционных функций
До ES2015 во всем использовались традиционные функции. Он используется для инкапсуляции кода, используется в качестве блоков, используется для конструкторов, как мы использовали выше, для обратных вызовов и т. Д.
Большинство этих случаев было заменено другими конструкторами, которые были представлены в ES2015.
Если мы хотим инкапсулировать код, мы можем использовать блоки. Например, вместо написания выражения немедленно вызываемой функции (IIFE) следующим образом:
(function() { let x = 1; console.log(x); })()
Вместо этого мы можем написать:
{ let x = 1; console.log(x); }
Второй пример короче, и нам нужно только ограничить блок фигурными скобками.
Переменная x
недоступна за пределами блока с приведенным выше кодом.
Другой способ инкапсулировать код - использовать модули. Например, мы можем написать следующий код:
module.js
export const x = 1; const y = 2; const z = 3; export default y;
index.js
import { x } from "./module"; import y from "./module"; console.log(x, y);
В приведенном выше коде мы открываем только то, что у нас есть, при экспорте с ключевым словом export
. Следовательно, x
и y
доступны для импорта из другого модуля.
Как видим, x
и y
были импортированы из module.js
. Но z
не могло быть, потому что он не экспортировался.
Следовательно, нам больше не нужны следующие IIFE:
const module = (function() { const x = 1; const y = 2; const z = 3; return { x, y } })();
Приведенный выше код длиннее и без надобности использует функцию. Кроме того, по мере того, как функция имеет больше членов, она становится длиннее, и иметь длинные функции - не лучшая идея.
Для обратных вызовов мы можем использовать вместо них стрелочные функции. Например, вместо того, чтобы писать:
const arr = [1, 2, 3].map(function(a) { return a * 2; })
Мы должны написать:
const arr = [1, 2, 3].map(a => a * 2)
Он короче, поэтому нам не нужно столько печатать, как не нужно вводить ключевое слово function
. Кроме того, возврат является неявным для функций с одной линией стрелки. И нам также не нужно беспокоиться о значениях this
и arguments
, поскольку стрелочные функции не привязываются ни к одному из этих значений.
Заключение
Для рефакторинга функций мы должны преобразовать конструкторы в классы. В противном случае мы должны преобразовать их в блоки, модули и стрелочные функции по своему усмотрению.