Javascript обзор языка преимущества недостатки. Язык программирования JavaScript: информация для начинающих. Введение в создание сценариев DOM

Аннотация: В лекции рассматривается недостатки, достоинства JavaScript. Обычные применения языка. . Современные применения JavaScript.

Введение

Теперь, после знакомства с сущностью основных концепций программирования, надо сделать шаг назад от деталей и попытаться получить общее представление о том, что в действительности можно делать с помощью JavaScript - зачем нужно тратить время на изучение такого сложного предмета и использовать его на Web -страницах?

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

Давайте двинемся вперед - эта лекция имеет следующую структуру:

  • Как я полюбил JavaScript
  • Недостатки JavaScript
  • Что может делать JavaScript
  • Обычные применения JavaScript
    • Введение в создание сценариев DOM
  • Заключение

Как я полюбил JavaScript

Когда я впервые столкнулся с JavaScript, компьютеры были медленными, браузеры плохо интерпретировали его, и он вообще казался просто плохой идеей. Я пришел из мира серверной разработки - поддерживайте все функции на Perl, и вы будете в безопасности.

С другой стороны скорость Интернета была очень медленной, а стоимость обработки и хранения файлов на сервере была очень высокой, и здесь JavaScript оказался на своем месте. Язык выполнялся на компьютерах конечных пользователей, и все, что можно было сделать на JavaScript, не создавало никакой дополнительной вычислительной нагрузки на сервере. Это делало сайты более быстрыми для конечного пользователя и менее дорогими для владельца в терминах серверного трафика.

Если перейти к сегодняшнему дню, то и браузеры стали лучше обрабатывать JavaScript, и компьютеры стали быстрее, и полоса пропускания значительно дешевле, так что большая часть недостатков стала теперь менее критичной. Однако уменьшение объема обмена информацией с сервером при использовании JavaScript по-прежнему ведет к более быстродействующим приложениям Web и улучшает восприятие сайта пользователем.

Недостатки JavaScript

Даже при всех улучшениях последнего времени по-прежнему существует ловушка : JavaScript является непредсказуемым. Не сам язык, а среда, в которой он реализуется. Невозможно предсказать, какой компьютер имеется у запрашивающего Web -страницу пользователя, невозможно знать, как загружен компьютер другими задачами, и невозможно знать, что какой-то другой сценарий JavaScript, открытый на другой вкладке браузера, приводит к полной остановке. Пока браузеры вообще не начнут выделять отдельные вычислительные ресурсы для различных вкладок и окон (известных как потоки), это по-прежнему будет оставаться проблемой. Мультипоточность стала, впрочем, доступной в некоторой степени в HTML5 с помощью Web workers , и имеет определенную поддержку в браузерах.

Кроме того, JavaScript часто отключают в браузерах из соображений безопасности, или потому что JavaScript часто используют для излишнего беспокойства пользователей, а не для улучшения взаимодействия. Например, все еще можно встретить множество сайтов, которые пытаются порождать новые окна вопреки желанию пользователя, или закрывать содержание сайта рекламой, пока пользователь не щелкнет на ссылке, чтобы от нее избавиться.

Что может делать JavaScript

Давайте вернемся на шаг назад и перечислим достоинства JavaScript:

  • JavaScript очень легко реализовать. Необходимо только поместить код в документ HTML и сообщить браузеру, что это JavaScript.
  • JavaScript работает на компьютерах пользователей web - даже когда они не в сети!
  • JavaScript позволяет создавать быстродействующие интерфейсы, которые улучшают восприятие пользователя и предоставляют динамические функции, не требуя ожидания реакции сервера и вывода другой страницы.
  • JavaScript может загружать контент в документ, когда и если это требуется пользователю, без перезагрузки всей страницы - что обычно называют Ajax .
  • JavaScript может проверить, что можно выполнить в браузере и реагировать соответственным образом - это называется Принципами ненавязчивого JavaScript (см. "Принципы ненавязчивого JavaScript") или иногда безопасным созданием сценариев.
  • JavaScript может помочь исправить проблемы браузера или закрыть пробелы в поддержке браузера - например, исправить в некоторых браузерах проблемы компоновки CSS.

Это уже много для языка, который еще недавно подвергался насмешкам со стороны программистов, приверженцев "языков программирования более высокого уровня". Одна из причин возрождения JavaScript в том, что сегодня создаются все более сложные приложения Web , и высокая интерактивность требует использования Flash (или других плагинов ) или создания сценариев. JavaScript является, возможно, лучшим способом, так как он является стандартным для Web , поддерживается изначально различными браузерами (более или менее - некоторые вещи различаются в разных браузерах, и эти различия рассматриваются в подходящих местах в последующих лекциях), и он совместим с другими открытыми стандартами Web .

Обычные применения JavaScript

Область применения JavaScript изменилась за те годы, что он использовался. Сначала взаимодействие JavaScript с сайтом было в основном ограничено взаимодействием с формами, предоставляя пользователю обратную связь , и слежения, когда они делали определенные вещи. Использовались функции alert() для уведомления пользователя о чем-то (см. рисунок 2.1), confirm () , чтобы спросить разрешение для выполнения какого-то действия, и prompt() или поле формы, чтобы получить ввод пользователя.


Рис. 2.1.

Это вело в основном к сценариям проверки , которые не позволяли пользователю отправить форму на сервер с ошибками, и простым преобразователям и калькуляторам. Кроме того, можно было также создавать совершенно бесполезные вещи, например, предложить пользователю ввести свое имя, чтобы сразу после этого вывести его.

Кроме того, использовалась функция document.write() для добавления контента в документ. Работали также с всплывающими окнами и фреймами и потратили много нервов и выдрали много волос в попытках заставить их общаться друг с другом. Только мысли о большинстве этих технологий должны заставить любого разработчика с отвращением пробормотать "пусть они исчезнут", поэтому давайте не будем останавливаться на таких вещах - существуют лучшие способы использования JavaScript!

Введение в создание сценариев DOM

Когда браузеры начали поддерживать и реализовывать Объектную модель документа - DOM (http://www.w3.org/DOM/), которая позволяет иметь значительно более развитое взаимодействие со страницами Web, JavaScript стал становиться более интересным.

DOM является объектным представлением документа. Предыдущий параграф, например, на языке DOM будет узлом элемента, имя узла nodeName которого будет p . Он содержит три узла потомка - текстовый узел, содержащий "Когда браузеры начали поддерживать и реализовывать" и его значение узла nodeValue , узел элемента с nodeName равным a , и еще один текстовый узел с nodeValue равным "которая позволяет иметь значительно более развитое взаимодействие со страницами Web, JavaScript стал становиться более интересным.". Узел потомок a также имеет узел атрибут, называемый href со значением "http://www.w3.org/DOM/ " и узел потомок, который является текстовым узлом с nodeValue равным " Объектную модель документа - DOM ".

Этот параграф можно представить также визуально, используя древовидную диаграмму, представленную на рисунке 2.2 .

На человеческом языке можно сказать, что DOM объясняет типы, значения и иерархию всего документа - на данный момент больше ничего знать не требуется. DOM будет подробнее рассмотрен в "Перемещение в DOM" , Общее знакомство с DOM , данного курса.

С помощью DOM можно:

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

Это означает, что больше не требуется использовать окна, фреймы, формы и ужасные предупреждающие сообщения , и можно передать пользователю ответ в документ в хорошо оформленном виде, как показано на рисунке 2.3 .

Вместе с обработкой событий это становится мощным арсеналом для создания интерактивных и привлекательных интерфейсов.

Обработка событий означает, что код реагирует на события, которые происходят в браузере. Это могут быть события, которые происходят автоматически - такие как окончание загрузки страницы - но большую часть времени реакция относится к тому, что пользователь делает в браузере.

Пользователи могут изменять размер окна, прокручивать страницу, нажимать определенные клавиши, или щелкать на ссылках, кнопках и элементах с помощью мыши. С помощью обработки событий можно ожидать возникновения этих событий, и приказать web-странице ответить на эти действия желательным образом. В то время как в прошлом щелчок на любой ссылке должен был переместить посетителя сайта к другому документу, теперь можно подменить эти действия и сделать что-то другое, например, показать и скрыть панель или извлечь информацию из ссылки и использовать ее для соединения с Web-службой.

События подробно рассматриваются в "Обработка событий с помощью JavaScript" , Обработка событий в JavaScript, далее в этом курсе.

Другие современные применения JavaScript

Вот в основном то, что сегодня делают с помощью JavaScript. Улучшают старые, проверенные и надежные Web-интерфейсы - щелчки на ссылках, ввод информации и отправку форм, и т.д. - чтобы быстрее реагировать на запросы конечного пользователя. Например:

  • Регистрационная форма может проверять при вводе, что имя пользователя доступно, позволяя избежать неприятного разочарования при перезагрузке страницы.
  • Поле поиска может предлагать на выбор какие-то варианты, пока происходит ввод, на основе того, что уже было введено (например, ввод "bi" может вызвать на выбор варианты слов, содержащих эту строку, такие как "bird", "big" и "bicycle"). Такая модель использования называется автозаполнением.
  • Информация, которая постоянно изменяется, может загружаться периодически, без необходимости взаимодействия с пользователем, например, результаты спортивного матча или котировки фондовой биржи.
  • Информация, которую хорошо бы иметь, и есть риск, что она будет избыточна для некоторых пользователей, может загружаться, когда и если пользователь решает к ней обратиться. Например, навигационное меню на сайте может иметь 6 ссылок, но выводит ссылки на более глубоко расположенные страницы по запросу, когда пользователь активирует пункт меню.
  • JavaScript может исправлять проблемы компоновки. С помощью JavaScript можно найти положение и площадь любого элемента на странице, а также размеры окна браузера. Используя эту информацию можно предотвратить перекрытие элементов и другие подобные проблемы. Предположим, например, что имеется меню с несколькими уровнями, проверяя перед выводом, что имеется пространство для представления подменю, можно избежать появления полос прокрутки или перекрытия пунктов меню.
  • JavaScript может улучшать интерфейсы, которые предоставляет HTML. Хотя иметь текстовое поле ввода и удобно, но еще лучше иметь поле ввода, позволяющее выбрать из списка предварительно заданных значений или ввести свое собственное. Используя JavaScript можно соответственно усовершенствовать обычное поле ввода.
  • JavaScript можно использовать для анимирования элементов на странице - например, чтобы показывать и скрывать информацию, или выделять определенные разделы страницы - это можно сделать для получения еще более удобного и развитого интерфейса пользователя. Дополнительная информация о таких возможностях представлена в "Анимация в JavaScript" , Анимация JavaScript, далее в этом курсе.

Использование JavaScript благоразумно и ответственно

Существует не так много такого, что вы не можете сделать с помощью JavaScript - особенно при соединении с другими технологиями, такими как Canvas или SVG . Однако при больших возможностях приходит большая ответственность, и всегда при использовании JavaScript нужно помнить о следующем.

  • JavaScript может быть недоступен - это легко проверить, поэтому не является проблемой. Однако вещи, которые зависят от JavaScript, должны создаваться с учетом этого фактора, и необходимо быть осторожным, чтобы сайт не перестал работать (т.е. основная функциональность не стала бы недоступна), если JavaScript будет недоступен.
  • Если использование JavaScript не помогает пользователю в достижении его цели более быстро и эффективно, то, вероятно, он используется неправильно.
  • Использование JavaScript часто нарушает соглашения, которые люди привыкли использовать за годы использования Web (например, щелчок на ссылке для перехода на другую страницу, и небольшая пиктограмма корзины, означающая "корзина для покупок"). Хотя эти шаблоны использования могут быть устаревшими и неэффективными, их изменение, тем не менее, заставляет пользователя изменить свои привычки - и это вызывает у людей чувство беспокойства. Мы любим все держать под контролем, и когда поняли что-то, порой бывает трудно иметь дело с изменениями. Решения JavaScript должны восприниматься естественно лучше, чем предыдущее взаимодействие, но не настолько отлично, что пользователь не сможет воспринять его через свой предыдущий опыт. Если вы сможете заставить посетителя сайта сказать: - "ага - это значит, я не должен ждать" или "Отлично - теперь я не должен делать этот дополнительный раздражающий шаг"- вы нашли отличное применение для JavaScript.
  • CSS . С помощью подходящих дополнительных модулей браузера (таких как Google Gears или Yahoo Browser Plus) можно даже использовать JavaScript, чтобы сделать онлайновые системы доступными в автономном режиме и синхронизироваться автоматически, когда компьютер подключается к сети.

    JavaScript не ограничен также только браузерами. Скорость и небольшие требования к памяти JavaScript по сравнению с другими языками программирования позволяют находить для него все новые применения - от автоматизации повторяющихся задач в таких программах как Illustrator, до использования его в качестве серверного языка с автономным синтаксическим анализатором. Будущее является широко открытым; неважно, что вы собираетесь делать как web -разработчик в ближайшем будущем, я совершенно уверен, вам рано или поздно придется работать с JavaScript.

    Об авторе

    Крис Хайлман работает Web -разработчиком уже десять лет, с тех пор как бросил радио-журналистику. Он работает для Yahoo! в Великобритании в качестве инструктора и ведущего разработчика, и осуществляет надзор за качеством кода внешнего представления для Европы и Азии.

    Крис поддерживает блог на сайте Wait till I come (http://wait-till-i.com/) и доступен во многих социальных сетях под ником "codepo8".

    Фото с разрешения: Bluesmoon (

Теперь с синтаксисом покончено, давайте наконец перейдём к самому интересному: изучению преимуществ и недостатков использования статических типов.

Преимущество № 1: Вы можете заблаговременно находить баги и ошибки

Статическая проверка типов позволяет проверять, что определённый нами инвариант принимает значение true , даже не запуская программу. И если имеется какое-то нарушение этих инвариантов, оно будет обнаружено перед запуском программы, а не во время её работы.

Небольшой пример: предположим, что у нас небольшая функция, которая берёт радиус и вычисляет площадь:

Const calculateArea = (radius) => 3.14 * radius * radius; var area = calculateArea(3); // 28.26
Теперь если мы захотим передать функции радиус, который не является числом (типа «злоумышленник»)…

Var area = calculateArea("im evil"); // NaN
Нам вернётся NaN . Если какая-то функциональность основана на том, что функция calculateArea всегда возвращает число, то это приведёт к уязвимости или сбою. Не очень приятно, правда?

Если бы мы использовали статические типы, то определили бы конкретный тип передаваемых параметров и возвращаемых значений для этой функции:

Const calculateArea = (radius: number): number => 3.14 * radius * radius;
Попробуйте теперь передать что-нибудь кроме числа функции calculateArea - и Flow вернёт удобное и симпатичное сообщение:

CalculateArea("Im evil"); ^^^^^^^^^^^^^^^^^^^^^^^^^ function call calculateArea("Im evil"); ^^^^^^^^^ string. This type is incompatible with const calculateArea = (radius: number): number => 3.14 * radius * radius; ^^^^^^ number
Теперь у нас есть гарантия, что функция будет принимать только валидные числа на входе и возвращать результат только в виде валидных чисел.

Поскольку контролёр типов сообщает вам об ошибках прямо во время написания кода, это намного удобнее (и намного дешевле), чем поиск бага после того, как код отправлен заказчику.

Преимущество № 2: У вас появляется живая документация

Типы работают как живая, дышащая документация и для вас, и для других.

Чтобы понять каким образом, посмотрим на метод, который я однажды нашла в большой кодовой базе, с которой работала:

Function calculatePayoutDate(quote, amount, paymentMethod) { let payoutDate; /* business logic */ return payoutDate; }
На первый взгляд (и на второй, и на третий), совершенно непонятно, как использовать эту функцию.

Является ли quote числом? Или логическим значением? Платёжный метод - это объект? Или это может быть строка, которая представляет тип платёжного метода? Возвращает ли функция дату в строковом виде? Или это объект Date ?

Без понятия.

В то время я решила провести оценку всей деловой логики и делала grep по кодовой базе до тех пор, пока всё не выяснила. Но это слишком много работы только для того, чтобы понять, как работает простая функция.

С другой стороны, если бы написали что-то вроде такого:

Function calculatePayoutDate(quote: boolean, amount: number, paymentMethod: string): Date { let payoutDate; /* business logic */ return payoutDate; }
то немедленно стало бы ясно, какой тип данных функция принимает, а какой тип возвращает. Это пример того, как можно использовать статические типы для сообщения того, что функция намерена делать. Мы можем сообщить другим разработчикам, чего ожидаем от них, и можем увидеть, чего они ожидают от нас. Следующий раз, если кто-то соберётся использовать эту функцию, вопросов не возникнет.

Можно поспорить, что эта проблема решается добавлением комментариев к коду или документации:

/* @function Determines the payout date for a purchase @param {boolean} quote - Is this for a price quote? @param {boolean} amount - Purchase amount @param {string} paymentMethod - Type of payment method used for this purchase */ function calculatePayoutDate(quote, amount, paymentMethod) { let payoutDate; /* .... Business logic .... */ return payoutDate; };
Это работает. Но здесь гораздо больше слов. Кроме многословности, такие комментарии в коде трудно поддерживать, потому что они ненадёжные и не имеют структуры - некоторые разработчики пишут хорошие комментарии, а другие могут написать что-то непонятное, а некоторые вообще могут забыть оставить комментарий.

Особенно легко забыть обновить комментарий после рефакторинга. С другой стороны, у аннотаций типов чётко определённый синтаксис и структура, и они никогда не устареют, потому что закодированы в самом коде.

Преимущество № 3: Устраняется обработка запутанных ошибок

Типы помогают устранить обработку в коде запутанных ошибок. Давайте вернёмся к нашей функции calculateArea и посмотрим, каким образом это происходит.

На этот раз я передам ей массив радиусов для вычисления площадей для каждого радиуса:

Const calculateAreas = (radii) => { var areas = ; for (let i = 0; i < radii.length; i++) { areas[i] = PI * (radii[i] * radii[i]); } return areas; };
Эта функция работает, но неправильно обрабатывает некорректные входные аргументы. Если мы захотим убедиться, что функция правильно обрабатывает ситуации, когда входные аргументы не являются валидными массивами чисел, то придём к функции примерно такого вида:

Const calculateAreas = (radii) => < radii.length; i++) { if (typeof radii[i] !== "number") { throw new Error("Array must contain valid numbers only"); } else { areas[i] = 3.14 * (radii[i] * radii[i]); } } return areas; };
Ого. Тут много кода для такого маленького кусочка функциональности.

А со статическими типами мы просто напишем:

): Array => < radii.length; i++) { areas[i] = 3.14 * (radii[i] * radii[i]); } return areas; };
Теперь функция действительно выглядит так, как она выглядела перед добавлением всего визуального мусора из-за обработки ошибок.

Легко понять преимущества статических типов, правда?

Преимущество № 4: Вы можете увереннее осуществлять рефакторинг

Объясню это историей из жизни. Однажды я работала с очень большой кодовой базой, и нужно было обновить метод, установленный в классе User . В частности, изменить один из параметров функции со string на object .

Я произвела изменение, но мне было страшно отправлять коммит - по всему коду разбросано так много вызовов к этой функции, что я не была уверена, что правильно обновила все экземпляры. Что если какой-то вызов остался где-то глубоко в непроверенном вспомогательном файле?

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

При использовании статических типов такой проблемы не возникнет. Там у меня будет мир и спокойствие в душе: если я обновлю функцию и определения типов, то контролёр типов будет рядом и обнаружит все ошибки, которые я могла упустить. Останется только пройтись по этим ошибкам типов и исправить их.

Преимущество № 5: Разделение данных и поведения

Одно редко упоминаемое преимущество статических типов состоит в том, что они помогают отделяют данные от поведения.

Ещё раз посмотрим на нашу функцию calculateArea со статическими типами:

Const calculateAreas = (radii: Array): Array => { var areas = ; for (var i = 0; i < radii.length; i++) { areas[i] = 3.14 * (radii[i] * radii[i]); } return areas; };
Подумайте, как бы мы подошли к составлению этой функции. Поскольку мы указываем типы данных, то вынуждены в первую очередь думать о типах данных, которые собираемся использовать, чтобы можно было соответствующим образом установить типы для передаваемых параметров и возвращаемых значений.

Только после этого мы реализуем логику:

Возможность точно выразить данные отдельно от поведения позволяет явно указать наши предположения и более точно передать намерение, что снимает определённую ментальную нагрузку и даёт программисту определённую ясность ума. Иначе остаётся держать всё в уме каким-то образом.

Преимущество № 6: Устранение целой категории багов

Ошибки типов во время выполнения программы - одна из самых распространённых ошибок или багов, с которыми сталкиваются JavaScript-разработчики.

Например, предположим, что изначальное состояние приложения было установлено так:

Var appState = { isFetching: false, messages: , };
И предположим, что затем мы делаем вызов API, чтобы забрать сообщения и заполнить наш appState . Далее, у нашего приложения есть чрезмерно упрощённый компонент для просмотра, который забирает messages (указанные в состоянии выше) и отображает количество непрочитанных сообщений и каждое сообщение как элемент списка:

Import Message from "./Message"; const MyComponent = ({ messages }) => { return (

{ messages.map(message => )}
); };
Если вызов API для забора сообщений не сработал или вернул undefined , то вы столкнётесь с ошибкой типа в продакшне:

TypeError: Cannot read property ‘length’ of undefined
…и ваша программа завершится со сбоем. Вы потеряете клиента. Занавес.

Посмотрим, как могут помочь статические типы. Начнём с добавления типов Flow к состоянию приложения. Я использую псевдоним типа AppState для определения состояния:

Type AppState = { isFetching: boolean, messages: ?Array }; var appState: AppState = { isFetching: false, messages: null, };
Поскольку известно, что API для забора сообщений работают ненадёжно, то укажем для значения messages тип maybe для массива строк.

Так же как в прошлый раз, мы забираем сообщения через ненадёжный API и используем их в компоненте просмотра:

Import Message from "./Message"; const MyComponent = ({ messages }) => { return (

You have { messages.length } unread messages

{ messages.map(message => )}
); };
Но в этот момент Flow обнаружит ошибку и пожалуется:

^^^^^^ property `length`. Property cannot be accessed on possibly null value

You have {messages.length} unread messages

^^^^^^^^ null

You have {messages.length} unread messages

^^^^^^ property `length`. Property cannot be accessed on possibly undefined value

You have {messages.length} unread messages

^^^^^^^^ undefined { messages.map(message => )} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call of method `map`. Method cannot be called on possibly null value { messages.map(message => )} ^^^^^^^^ null { messages.map(message => )} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call of method `map`. Method cannot be called on possibly undefined value { messages.map(message => )} ^^^^^^^^ undefined
Погоди, приятель!

Поскольку мы определили messages как тип maybe , мы разрешаем ему быть null или undefined . Но это не даёт нам права проводить операции с ним (вроде.length или.map) без осуществления проверки на null , потому что если значение messages на самом деле null или undefined , то выскочит ошибка типа при попытке проведения операции с ним.

Так что вернёмся и обновим нашу функцию для просмотра примерно таким образом:

Const MyComponent = ({ messages, isFetching }: AppState) => { if (isFetching) { return } else if (messages === null || messages === undefined) { return

Failed to load messages. Try again.
} else { return (

You have { messages.length } unread messages

{ messages.map(message => )}
); } };
Теперь Flow знает, что мы учли все ситуации, где messages равно null или undefined , так что проверка типов кода завершается с 0 ошибок. Прощайте, ошибки во время выполнения программы!

Преимущество № 7: Уменьшение количества юнит-тестов

Раньше мы видели, как статические типы помогают избавиться от разбора запутанных ошибок, потому что они гарантируют типы передаваемых функции параметров и возвращаемых значений. Как следствие, статические типы также уменьшают количество юнит-тестов.

Например, вернёмся к нашей функции calculateAreas с динамическими типами и обработкой ошибок.

Const calculateAreas = (radii) => { // Handle undefined or null input if (!radii) { throw new Error("Argument is missing"); } // Handle non-array inputs if (!Array.isArray(radii)) { throw new Error("Argument must be an array"); } var areas = ; for (var i = 0; i < radii.length; i++) { if (typeof radii[i] !== "number") { throw new Error("Array must contain valid numbers only"); } else { areas[i] = 3.14 * (radii[i] * radii[i]); } } return areas; };
Если бы мы были прилежными программистами, то могли бы подумать о тестировании недействительных передаваемых параметров для проверки, что они корректно обрабатываются нашей программой:

It("should not work - case 1", () => { expect(() => calculateAreas()).to.throw(Error); }); it("should not work - case 2", () => { expect(() => calculateAreas(undefined).to.throw(Error); }); it("should not work - case 2", () => { expect(() => calculateAreas("hello")).to.throw(Error); });
… и так далее. Но очень вероятно, что мы забудем протестировать какие-то граничные случаи, - и наш заказчик будет тем, кто обнаружит проблему. :(

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

С другой стороны, когда нам требуется установить типы:

Const calculateAreas = (radii: Array): Array => { var areas = ; for (var i = 0; i < radii.length; i++) { areas[i] = 3.14 * (radii[i] * radii[i]); } return areas; };
… мы не только получаем гарантию, что наша цель соответствует реальности, но такие тесты попросту надёжнее. В отличие от тестов на эмпирической основе, типы универсальны и их труднее обойти.

Если взглянуть в целом, то картина такова: тесты хороши для проверки логики, а типы - для проверки типов данных. Когда они сочетаются, то сумма частей даёт ещё больший эффект.

Преимущество № 8: Инструмент моделирования предметной области

Один из моих любимых примеров использования статичных типов - моделирование предметной области (domain modeling). В этом случае создаётся модель, которая включает в себя и данные, и поведение программы на этих данных. В данном случае лучше всего понять на примере, как использовать типы.

Предположим, что в приложении пользователю предлагается один или больше платёжных методов для совершения покупок на платформе. Пользователю разрешено выбрать из трёх платёжных методов (Paypal, кредитная карта, банковский счёт).

Итак, сначала применим псевдонимы типов для трёх платёжных методов:

Type Paypal = { id: number, type: "Paypal" }; type CreditCard = { id: number, type: "CreditCard" }; type Bank = { id: number, type: "Bank" };
Теперь можно установить тип PaymentMethod как непересекающееся множество с тремя случаями:

Type PaymentMethod = Paypal | CreditCard | Bank;
Теперь составим модель состояния нашего приложения. Чтобы не усложнять, предположим, что данные приложения состоят только из платёжных методов, доступных пользователю.

Type Model = { paymentMethods: Array };
Это приемлемо? Ну, мы знаем, что для получения платёжных методов пользователя нужно сделать запрос к API и, в зависимости от результата и этапа процесса, приложение может принимать разные состояния. В реальности, возможно четыре состояния:

1) Мы не получили платёжные методы.
2) Мы в процессе получения платёжных методов.
3) Мы успешно получили платёжные методы.
4) Мы попытались получить платёжные методы, но возникла ошибка.

Но наш простой тип Model с paymentMethods не покрывает все эти случаи. Вместо этого он предполагает, что paymentMethods всегда существует.

Хм-м-м. Существует ли способ составить модель, чтобы состояние приложения принимало одно из этих четырёх значений, и только их? Давайте посмотрим:

Type AppState = { type: "NotFetched" } | { type: "Fetching" } | { type: "Failure", error: E } | { type: "Success", paymentMethods: Array };
Мы использовали тип непересекающегося множества для установки AppState в одно из четырёх состояний, описанных выше. Заметьте, как я использую свойство type для определения, в каком из четырёх состояний находится приложение. Именно это свойство type и является тем, что создаёт непересекающееся множество. Используя его мы можем осуществить анализ и определить, когда у нас есть платёжные методы, а когда нет.

Вы также заметите, что я передаю параметризованный тип E и D в состояние приложения. Тип D будет представлять собой платёжный метод пользователя (PaymentMethod , определённый выше). Мы не установили тип E , который будет нашим типом для ошибки, так что сделаем это сейчас:

Type HttpError = { id: string, message: string };
Теперь можно смоделировать предметную область приложения:

Type Model = AppState;
В целом, подпись для состояния приложения теперь AppState , где E имеет форму HttpError , а D - это PaymentMethod . И у AppState есть четыре (и только эти четыре) возможных состояния: NotFetched , Fetching , Failure и Success .

Такие модели предметной области мне кажутся полезными для размышлений и разработки пользовательских интерфейсов в соответствии с определёнными бизнес-правилами. Бизнес-правила говорят нам, что приложение может быть только в одном из этих состояний, и это позволяет нам явно представить AppState и гарантировать, что оно будет только в одном из этих заранее установленных состояний. И когда мы разрабатываем по этой модели (например, создаём компонент для просмотра), становится абсолютно очевидно, что нужно обработать все четыре возможных состояния.

Более того, код документирует сам себя - достаточно посмотреть на непересекающиеся множества, и немедленно становится понятно, как структурирован AppState.

Недостатки использования статических типов

Как и всё остальное в жизни и программировании, проверка статических типов требует некоторых компромиссов.

Важно понять и признать эти недостатки, чтобы мы могли принять информированное решение, когда имеет смысл использовать статические типы, а когда они просто не стоят того.

Вот некоторые из этих соображений:

Недостаток № 1: Статические типы требуют предварительного изучения

Одна причина, почему JavaScript - такой фантастический язык для начинающих, состоит в том, что новичкам не требуется изучать полную систему типов перед началом продуктивной работы.

Когда я только выучила Elm (функциональный язык со статической типизацией), типы часто мешали. Я постоянно сталкивалась с ошибками компилятора из-за своих определений типов.

Изучение эффективного использования типов - это была половина успеха в изучении самого языка. В итоге, из-за статических типов кривая обучения Elm круче, чем у JavaScript.

Это особенно важно для начинающих, у которых максимально велика когнитивная нагрузка от изучения синтаксиса. Добавление синтаксиса в этот набор может сокрушить новичка.

Недостаток № 2: Можно увязнуть в многословии

Из-за статических типов программы часто выглядят более многословными и загромождёнными.

Например, вместо этого:

Async function amountExceedsPurchaseLimit(amount, getPurchaseLimit){ var limit = await getPurchaseLimit(); return limit > amount; }
Нам приходится писать:

Async function amountExceedsPurchaseLimit(amount: number, getPurchaseLimit: () => Promise): Promise { var limit = await getPurchaseLimit(); return limit > amount; }
А вместо этого:

Var user = { id: 123456, name: "Preethi", city: "San Francisco", };
Приходится писать такое:

Type User = { id: number, name: string, city: string, }; var user: User = { id: 123456, name: "Preethi", city: "San Francisco", };
Очевидно, что добавляются лишние строки кода. Но есть парочка аргументов против того, чтобы считать это недостатком.

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

Во-вторых, как мы видели раньше, статические типы иногда могут устранить необходимость обработки сложных ошибок, и это, в свою очередь, значительно уменьшает загромождённость кода.

Сложно сказать, является ли многословность реальным аргументом против типов, но стóит держать его в уме.

Недостаток № 3: Требуется время для достижения мастерства в использовании типов

Требуется много времени и практики, чтобы научиться наилучшим образом выбирать типы в программе. Более того, выработка хорошего чутья на то, что стоит отслеживать статически, а что лучше оставить в динамическом виде, тоже требует аккуратного подхода, практики и опыта.

Например, один из подходов такой: закодировать критическиую бизнес-логику статическими типами, но оставить краткосрочные или неважные фрагменты логики динамическими, чтобы избежать излишней сложности.

Понять разницу бывает трудно, особенно если менее опытному разработчику приходится принимать решения на лету.

Недостаток № 4: Статические типы могут задержать быструю разработку

Как я упоминала ранее, я слегка споткнулась о типы, когда изучала Elm - особенно когда добавляла код или делала изменения в нём. Постоянно отвлекаясь на ошибки компилятора, трудно делать работу и чувствовать прогресс.

Здесь аргумент в том, что из-за проверки статических типов программист может слишком часто терять концентрацию - а вы знаете, концентрация является ключевым фактором для написания хорошей программы.

Дело не только в этом. Контролёры статических типов тоже не всегда идеальны. Иногда возникает ситуация, когда вы знаете что делать, а проверка типов вмешивается и мешает.

Уверена, что я упустила какие-то ещё недостатки, но это самые важные для меня.

Нужно использовать статические типы в JavaScript или нет?


Первыми языками программирования, которые я изучила, были JavaScript и Python, оба языка с динамической типизацией.

Но освоение статических типов добавило новое измерение в то, как я думаю о программировании. Например, хотя я считала постоянные сообщения об ошибках компилятора в Elm подавляющими в первое время, потом определение типов и «угождение компилятору» стало второй натурой и на самом деле улучшило мои навыки программирования. Вдобавок, нет ничего более освобождающего, чем умный робот, который говорит мне, что я делаю что-то не так и как это исправить.

Да, есть неизбежные компромиссы статических типов, такие как излишняя многословность и необходимость тратить время на их изучение. Но типы добавляют безопасность и корректность в программы, что устраняет значимость этих «недостатков» для меня лично.

Динамические типы кажутся более быстрыми и простыми, но они могут подвести, когда вы реально запускаете программу в деле. В то же время можете поговорить с любым Java-разработчиком, который имеет дело с более сложными параметризованными типам - и он скажет, как сильно их ненавидит.

В конечном счёте, здесь нет универсального решения. Лично я предпочитают использовать статические типы при следующих условиях:

  1. Программа критически важна для вашего бизнеса.
  2. Программа, вероятно, подвергнется рефакторингу, в соответствии с новыми потребностями.
  3. Программа сложна и имеет много подвижных частей.
  4. Программу поддерживает большая группа разработчиков, которым нужно быстро и точно понять код.
С другой стороны, я бы отказалась от статических типов в следующих условиях:
  1. Код недолговечный и не является критически важным.
  2. Вы делаете прототип и стараетесь продвигаться как можно быстрее.
  3. Программа маленькая и/или простая.
  4. Вы единственный разработчик.
Преимущество разработки на JavaScript в наши дни состоит в том, что благодаря инструментам вроде Flow и TypeScript у нас наконец-то появился выбор - использовать статические типы или старый добрый JavaScript.

Заключение

Надеюсь, эти статьи помогли вам понять важность типов, как их использовать и, самое главное, *когда* их использовать.

Возможность переключаться между динамическими и статическими типами - это мощный инструмент для JavaScript-сообщества, и захватывающий:)

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

Назовите две наиболее важные для JavaScript-разработчика парадигмы программирования?

JavaScript – мультипарадигмальный язык, поддерживающий императивное/процедурное программирования наряду с ООП и функциональным программированием. JS поддерживает ООП с прототипным наследованием.

Желательно упомянуть:

1. Прототипное наследование (также: прототипы, объектные ссылки)

2. Функциональное программирование (также: замыкания, функции первого класса, лямбды)

Следует избегать:

Не иметь представления о парадигмах, не упомянуть прототипное ООП или функциональное программирование.

Что такое функциональное программирование?

Функциональное программирование подразумевает вычисление математических функций, избегая общих состояний и изменяемых данных. Lisp (специфицирован в 1958 году) является одним из первых функциональных языков программирования и сильно вдохновлен лямбда-исчислениями. Lisp и подобные ему языки широко применяются и по сей день.

Функциональное программирование – одна из основополагающих концепций JavaScript (один из двух столпов JS). Некоторые функциональные утилиты были добавлены в JavaScript в ES5.

Хорошо упомянуть:

1. Чистые функции / чистота функций

2. Избежание побочных эффектов

3. Простой состав функций

4. Примеры функциональных языков: Lisp, ML, Haskell, Erlang, Clojure, Elm, F Sharp, OCaml и т.д.

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

Следует избегать:

1. Отсутствие упоминаний чистых функций / избежание побочных эффектов

2. Не привести примеры функциональных языков

3. Не привести примеры функциональных фич JavaScript

В чем заключается разница между классовым и прототипным наследованием?

Классовое наследование: экземпляры наследуются от классов, создаются подклассовые отношения (иерархическая систематизация классов). Экземпляры реализуются через конструктор функции, через дескриптор new. Экземпляр класса может не содержать дескриптор class начиная с ES6.

Прототипное наследование: экземпляры наследуются напрямую от других объектов, реализуются через фабрики или Object.create() и экземпляры могут быть составлены из множества различных объектов для упрощения выборочного наследования. Прототипное наследование более простое и гибкое, нежели классовое.

Хорошо упомянуть:

1. Классы: тесные связи, иерархия

2. Прототипы: конкатенативное наследование, делегирование, функциональное наследование, композиция

Следует избегать:

Не указать на преимущества прототипного наследования перед классовым

Каковы плюсы и минусы функционального и объектно-ориентированного программирования?

Плюсы ООП: простая для понимания концепция объектов и методов вызова. ООП стремится использовать императивный стиль, нежели декларативный, который читается как прямой набор машинных инструкций.

Минусы ООП: как правило, присутствует зависимость от общих состояний. Объекты и их поведение связаны одной сущностью, к которой случайно может быть получен доступ любым количеством функций в неопределенном порядке, что может привести к непредсказуемому поведению, например, состоянию гонки.

Плюсы ФП: используется функциональная парадигма, позволяющая избежать общих состояний и нежелательных эффектов, исключаются ошибки, возможные из-за конкурирования функций. Благодаря таким фичам, как неявное программирование, функции, как правило, радикально упрощаются и легко перестраиваются для более легкого, по сравнению с ООП, повторного использования кода.

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

Минусы ФП: чрезмерная эксплуатация функциональных подходов, вроде неявного программирования, может привести к снижению читабельности кода, так как конечный код получается более абстрактным, кратким и менее конкретным.

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

Функциональное программирование имеет более крутую кривую обучения, нежели ООП, имеющего большую популярность и более понятного для изучения. Концепции ФП часто описываются идиомами и обозначениями из лямбда-исчислений, алгебры и теории категорий, требующих знаний основ в этих областях для понимания.

Хорошо упомянуть:

1. Проблемы общих состояний, нежелательного поведения

2. Возможности ФП по радикальному упрощению кода программ

3. Разность в сложности изучения

4. Побочные эффекты и их влияние на надежность программ

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

Следует избегать:

Не упомянуть недостатки одного из подходов – каждый, кто сталкивался с одним из них, знает и о паре-другой недостатков

Когда классовое наследование – подходящий выбор?

Вопрос с подвохом. Правильный ответ – никогда. Композиция – более простой и гибкий подход, чем наследование классов.

Хорошо упомянуть

«…композиция объектов лучше, чем наследование классов»

Следует избегать:

Упоминание Rect Components. React.js использует дескриптор class, но не позволяет избежать подводных камней классового наследования. Вопреки популярным ответам, не нужно использовать class, чтобы пользоваться React. Такой ответ покажет не понимание как классов в JavaScript, так и Реакта.

Когда лучше использовать прототипное наследование?

Существует более, чем один тип прототипного наследования:

1. Делегирование (цепочка прототипов)

2. Конкатенация (миксины, Object.assign())

3. Функциональное наследование (не путать с функциональным программированием. Функция используется для создания замыкания для private/инкапсуляции)

Хороший ответ:

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

2. Когда нужно собрать объект из нескольких источников

3. В любом случае, когда нужно применить наследование

Следует избегать:

1. Не знать, когда применяются прототипы

2. Не знать о миксинах или Object.assign()

Что значит «композиция объектов лучше, чем наследование классов»?

Это цитата из книги “Design Patterns: Elements of Reusable Object-Oriented Software”. Повторное использование кода должно достигаться за счет сборки малых единиц функциональности в новый объект, а не наследованием классов и созданием иерархий.

Хорошо упомянуть:

1. Избежание наследования и тесных связей

2. Избежание вытекающей из классического наследования проблемы «банан/мартышка» (нужен был банан – получили мартышку, держащую банан посреди джунглей)

Следует избегать:

Не назвать какую-то из упомянутых выше проблем. Не объяснить разницу между композицией и наследованием или не суметь рассказать об преимуществах композиции.

Что такое двусторонняя связь данных и однонаправленный поток данных и в чем разница между ними?

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

Однонаправленный поток данных означает, что только модель – источник истины. Изменения в интерфейсе запускают сообщения, которые сигнализируют пользователю о намерении модели (или «store» в терминах React). Смысл в том, что данные всегда идут в одном направлении, что облегчает понимание.

Односторонние потоки данных детерминированы, тогда как двусторонняя привязка может вызывать нежелательные эффекты, которые труднее отследить и понять.

Хорошо упомянуть:

1. React – новый канонический пример однонаправленного потока данных, так что упоминание Реакта будет хорошей идеей. Cycle.js — еще одна популярная реализация однонаправленного потока данных.

2. Angular – популярный фреймворк, использующий двустороннюю привязку.

Следует избегать:

Непонимание этих концепций, неспособность объяснить разницу между ними.

Каковы плюсы и минусы монолитной архитектуры и микросервисов?

Монолитная архитектура означает, что ваше приложение написано как единый связный блок кода, чьи компоненты спроектированы для совместной работы и использования общих ресурсов.

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

Преимущества монолитной архитектуры: основным преимуществом монолитной архитектуры является то, что большинство приложений, как правило, имеют множество общих проблем, таких как логирование, ограничение скорости и необходимость функций безопасности – в едином приложении для каждого компонента их проще решать.

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

Плюсы микросервисов: микросервисы обычно лучше организованы, так как каждый компонент выполняет свою задачу и работает независимо от каждого другого компонента. Приложение на основе обособленных компонентов также проще переконфигурировать и изменять.

Минусы микросервисов: при создании нового микросервиса может появится много внезапных проблем, которые не ожидались при проектировании. Для монолитного приложения можно использовать промежуточное программное обеспечение для решения различных сквозных проблем без особых трудозатрат.

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

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

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

Хорошо упомянуть:

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

2. Практические различия микросервисов и монолитных приложений

Следует избегать:

1. Незнание различий архитектур

2. Незнание недостатков микросервисов

3. Недооценивать преимущества масштабирования микросервисов

Что такое асинхронное программирование и почему оно важно в JS?

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

Асинхронное программирование подразумевает, что когда требуется операция блокировки, запрос отправляется, и код продолжает работать без блокировки до ожидания результата. Когда ответ готов, запускается прерывание, это приводит к запуску обработчика событий и поток управления продолжается. Таким образом, один программный поток может обрабатывать множество параллельных операций.

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

Node.js по умолчанию асинхронен, по сути, сервер проводит все время в цикле, ожидая сетевой запрос.

В JavaScript это важно, так как естественно для интерфейсов и положительно сказывается на производительности сервера.

Хорошо упомянуть:

1. Значение блокировок, влияние на производительность

2. Понимание обработчиков и почему они важны для интерфейсов

Следует избегать:

1. Непонимание терминов синхронности и асинхронности

2. Неспособность определить последствия для производительности

Язык PHP применяется для разработки веб-приложений очень активно, и сегодня на нем работают три из пяти сайтов. Однако обязательно стоит обратить внимание и на возможные альтернативы. Одной из них является Node.js.

Преимущества Node.js

Количество поклонников этой программной платформы стремительно увеличивается, ведь во многих ситуациях она имеет неоспоримые преимущества перед PHP. Javascript, на котором пишется серверный код на Node.js — это мощный и гибкий язык. Он имеет свои особенности и даже странности, однако после того, как вы поймете его концепцию, работа на нем наверняка вас затянет. Javascript допускает программирование в разных стилях и предоставляет разработчику большие возможности.

Node.js дополнительно расширяет его функционал. Если раньше Javascript использовался исключительно для разработки браузерных приложений, то теперь на нем можно писать также приложения мобильные и десктопные. PHP тоже можно применять для разработки десктопных приложений и консольных утилит, но делается это достаточно редко.

По умолчанию Node.js укомплектована удобным и функциональным менеджером пакетов — npm. Он делает управление модулями и зависимостями простым и комфортным. А благодаря встроенным библиотекам для обработки запросов и ответов с Нодой вы не будете зависеть от сторонних серверов. Также эта платформа в некоторых ситуациях обеспечивает лучшую производительность.

И, наконец, Node.js имеет большое количество положительных отзывов от разработчиков. Немногие из тех, кто пишут на PHP, увлечены этим языком, но с Javascript ситуация совсем иная.

Недостатки

Однако надо иметь в виду, что Node не лишена недостатков:

  • она сложнее в изучении, и начать работать с использованием этой технологии будет не так легко, особенно в том случае, если вы новичок в веб-программировании, в то время как создать сайт на PHP гораздо проще;
  • технология Node относительно молода, поэтому информации по ней гораздо меньше, чем по PHP;
  • для PHP подойдет любой хостинг, а вот подходящую площадку для Node придется еще поискать;

Таким образом, однозначного ответа на вопрос о том, что лучше — PHP или Node.js — нет. Однако нужно иметь в виду, что последняя стремительно набирает популярность. Сегодня ее используют Microsoft, PayPal, LinkedIn, Yahoo и множество других крупных компаний.

Многие еще с девяностых годов привыкли использовать PHP и не спешат его на что-то менять. Однако прогресс не стоит на месте, и технологии веб-разработки в последние годы развиваются стремительно. В том случае, если вы будете игнорировать новые веяния, рано или поздно вы заметите, что разрабатываемые вами продукты просто недостаточно актуальны и востребованы.

От автора: переход с React на Vue, два года спустя. Выбор новых фреймворков и библиотек — захватывающий, но также стрессовый процесс. Даже после определенного исследования вы никогда не знаете, какие скелеты обнаружите в шкафу.

Мой медовый месяц длится долго. Примерно через 2 года почти ежедневного использования Vue я, наконец, могу написать об этом, имея определенную точку зрения. Рассмотрим свойственные Vue js преимущества, не забудем и про недостатки. ОСТОРОЖНО: Личное мнение.

Хороший

Реактивность

Привязывание данных — это отличная вещь в мире интерфейсов. Вместо микроменеджмента DOM, как мы это делали с jQuery, теперь мы фокусируемся на данных. Vue обрабатывает их аккуратно с помощью двухсторонней реактивной системы привязки данных.

Чтобы достичь этой реактивности, Vue добавляет несколько геттеров и сеттеров к каждой переменной в состоянии, чтобы она могла отслеживать изменения и автоматически обновлять DOM (кхе-кхе, this.setState()). Этот подход не является совершенным, как мы увидим позже.

Батареи прилагаются

С Vue нам нет необходимости прибегать к неофициальным пакетам, таким как MobX или React Router, для критических частей приложения. Vue предоставляет Vue Router и Vuex, Redux-подобный реактивный инструмент для управления состояниями. Это отличные библиотеки сами по себе, но тот факт, что они были специально разработаны для Vue, делает их еще лучше.

Скорость

Vue очень быстр. Возможно, он не самый быстрый, но его производительности с запасом хватает для подавляющего большинства веб-проектов. Когда вам в последний раз нужен был рендеринг и обновление тысяч элементов DOM в секунду?

HTML-шаблоны

Это одна из тем, вызывающих разногласия среди разработчиков JavaScript. Независимо от ваших предпочтений, HTML-шаблоны были проверены в течении десятилетий использования во многих языках и являются основным выбором для написания динамической разметки во Vue.

Но эй, Vue поддерживает также и JSX.

Другие приятные вещи:

Отдельные файловые компоненты с HTML, CSS и JavaScript.

Легкий. Около 20 КБ (минимизированный + gzip).

Хорошо расширяемый (миксины, плагины и т. д.).

Отличная документация (за некоторыми исключениями, указанными ниже).

Может быть принят постепенно, даже используется как замена jQuery.

Просто начать использовать.

Неоднозначный

Шаблон компонентов

Переход от React к Vue выглядит как глоток свежего воздуха. Больше не существует привязки (this) или setState(). Ура! Но через некоторое время вы начнете подвергать сомнению правильность синтаксиса компонентов Vue. Компоненты Vue создаются с помощью объектов, и вот пример определения функции компонента:

export default { methods: { increment () { this.count++; } } }

export default {

methods : {

increment () {

this . count ++ ;

Вы будете добавлять аналогичный шаблон для вычисляемых свойств, состояния компонентов, наблюдателей и т. д. Практически все во Vue имеет собственный специальный синтаксис с большим количеством шаблонов. А вот то же самое для Марко , но это значительно чище:

class { increment() { this.state.count++; } }

class {

increment () {

this . state . count ++ ;

Сейчас я говорю не об использовании или не использовании классов, а о том, что Vue использует произвольные структуры объектов вместо языковых функций.

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

Чат-сообщество

Сообщество Vue зависает на Discord, чате, предназначенном для сообществ геймеров. Если вы попали в сложную ситуацию, чат, вероятно, будет вашим лучшим решением, поскольку официальные форумы — это пустынные земли, и вы ведь не хотите задавать вопрос на Github.

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

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

Не такой волшебный

Пока вы не сходите с проторенного пути, все будет хорошо, но через некоторое время вы, вероятно, найдете много маленьких если и но, связанных с Vue. Некоторые примеры:

Реактивная система отслеживает изменения только при определенных условиях. Не ожидайте, что вы можете вводить все, что пожелаете. Довольно часто вам может понадобиться максимально упростить данные, чтобы избежать головной боли. Конечно, все это объясняется мелким шрифтом в документации.

Переходная система не работает для списков. Вам на самом деле нужно использовать , который работает несколько иначе и вводит в DOM новые элементы. Кроме того, можно было бы ожидать, что для этого должно быть отличное решение, но вам придется реализовать его самостоятельно.

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

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

Злой

Нечеткие архитектурные шаблоны

Вот пример: что лучше — обрабатывать запросы API в компонентах или во Vuex? В документации приведены примеры того, как обрабатывать API-логику во Vuex. Есть даже красивая и красочная диаграмма:

Означает ли это, что логика аутентификации также входит во Vuex? Будет ли менеджер состояний начинать перехватывать всю логику приложения?

Это не очевидные вещи. Большинство людей просто начнут вставлять логику без состояний в действия Vuex или, что еще хуже, непосредственно в компоненты, потому что на домашней странице Vue есть видео:

Отвечая на первоначальный вопрос: логика API не должна писаться ни во Vuex, ни в компонентах. Существует даже хороший пример того, как это делается в официальных примерах кода .

Заключение

Все больше людей переходят на Vue, и я сомневаюсь, что эта тенденция скоро прекратится. Он все еще далеко не настолько принят, как React (по крайней мере, за пределами Китая), и постоянно борется за второе место с Angular.

В прошлом я утверждал, что Vue — это прагматичная библиотека, в отличие от React, которая кажется более идеалистической («Мы чистый JavaScript!»). Я все еще думаю, что это хорошая метафора. С другой стороны, теперь я чувствую, что прагматизм-для-всего от Vue нуждается в гораздо большей доводке, элегантности и простоте на уровне пользователя.

За 2 года мой опыт работы с Vue был положительным. Я все еще уверен, что это было хорошим решением перевести мою команду с React на Vue. Не потому, что Vue лучше, а потому, что он лучше подходит для нас.

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



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: