Рубрики
Без рубрики

JavaScript: что я не понял

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

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

Ловушка JavaScript

Давным-давно в галактике далеко, далеко я прибыл в новую команду. За мной сильная специализация PHP. Этот день был важен. Я сдался моя PHP религия Чтобы присоединиться к команде религии JavaScript.

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

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

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

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

Вся переписывание петли для продукта.

Не собираюсь в деталях, мы можем сравнить этот сервис к виду CDN. Клиент отправляет ZIP-файл, мой сервис должен управлять большим количеством вещей. Извлечение файла Fly Fly с рекурсией (ZIP в ZIP), загрузка, кэширование, статическое обслуживание файлов, версию, метаданные. Все это при сохранении 100% звонков под за 200 мс.

Делать такого рода вещь правильно требует внутреннего понимания того, как работает JavaScript. Я этого не знал. Я собирался страдать перед ошибками и непонятно поведением.

Ловушка JavaScript только что закрылась на меня.

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

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

Неизвестные переменные

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

Как требуется к тому времени, я пишу jQuery. Я думал, что был бог на этом. Мне удалось сделать все, что было спросино от меня. Несмотря на то, что я думал, время от времени у меня есть большие слепки в лице.

Простые вещи не работают. Это ошибки без причины. И как ни странно, тот факт, что я стучу на мою клавиатуру, не решит проблему.

Мои проблемы пришли с первого, что я не понял с JavaScript: внутренняя работа переменных и типов.

Чтобы понять, о чем я говорю, давайте посмотрим на какой-код.

* Что будет отображать этот код и почему? *

const originalEzio = {
  "name": "ezio Auditore da Firenze",
  "weapon": "Hidden Blade",
  "metadata": {
    "version": "Original",
    "type": "Assassin"
  }
};

originalEzio.name[0] = 'E';

function getHeroCopy(originalHero) {
  let copyHero = {
    name: originalHero.name,
    weapon: originalHero.weapon,
    metadata: originalHero.metadata
  };

  copyHero.metadata.version = 'Copy';

  return copyHero;
}

const copyOfEzio = getHeroCopy(originalEzio);

console.log('Original : ', originalEzio);
console.log('Copy : ', copyOfEzio);

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

Давайте проверим ваш прогноз, нажав PLAY на REFLENT ниже.

Если вы не можете объяснить этот результат, вы не пропустите что-то в основании языка. Краткое объяснение в нескольких словах.

Переменные делятся на две основные категории: примитивы и комплексы.

  • Примитивы (строка, номер, логический, …) указывают на уникальные значения.

Они неизменны. Следовательно, тот факт, что строка не меняется (строка 10). Кстати, если вы добавите «использовать строго» в начале файла, он немедленно бросает. В строгом мире JavaScript не допускает этого дьявора.

  • Комплексы (объект, …) указывают на стоимость ссылок.

Они смены. Линия 16, я обращаюсь к объекту метаданных оригинального героя и назначьте его на объект метаданных копии. Изменяя копию, я поэтому изменяю ссылку на оригинал.

Когда я начал, у меня не было этих понятий. И поверь мне, это не весело, не имеющее их. У многих людей их нет.

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

у меня есть Рекомендация Для вас в конце статьи, чтобы понять и преодолеть все эти подводные камни.

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

Что это чертов

Для переписывания сервиса мне помогло многие внутренние и внешние библиотеки. Некоторые более свежие, чем другие. Некоторые лучше сделаны, чем другие. Они использовали все объект размерности JavaScript.

Или точнее, прототипное ориентированное программирование, неполная форма объекта программирования.

Даже сегодня, несмотря на синтаксический сахар классов, он все еще прототипы. JavaScript не на самом деле объектно-язык. Увидимся в Twitter для некоторых бой тех, кто не согласен.

// what you use
class Assassin {
  constructor(name) {
    this.name = name;
  }

  getCreed() {
    return "Nothing is true, everything is permitted.";
  }
}

//---------------

// what JS really does behind
function Assassin(name){
  this.name = name;
}

Assassin.prototype.getCreed = function() {
  return "Nothing is true, everything is permitted.";
}

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

Опять же, раздражающий вопрос о мероприятии.

*** Что будет отображать этот код и почему? ** *

const altair = {
  name: "Altaïr Ibn-La'Ahad",
  templarsKilled: ['Tamir', 'Talal', 'Sibrand'],
  showTemplarsKilled: function() {
    console.log(`List of templar killed (${this.templarsKilled.length}) by ${this.name}`)

    this.templarsKilled.forEach(function(templarKilled) {
      console.log(`${this.name} killed ${templarKilled}`)
    });
  }
};

altair.showTemplarsKilled();

Вы можете проверить свой прогноз с помощью Reft чуть ниже.

Почему не работает второй журнал (строка 8)? Почему первый журнал (строка 5) работает? Почему использование функции стрелки (строка 7) решает проблему?

Если вы не можете ответить на эти вопросы, это потому, что знаменитый (этот) контекст JavaScript запятнается для вас. И это понятно. В JavaScript контекст не ведет себя вообще, как на других языках.

Мы имеем дело с монстром.

Теоретически, «это» представляет собой контекст функции. Объект, связанный с вызовом функции. За исключением того, что это не так просто. По правде говоря, он будет определен в соответствии с тем, как он называется.

Давайте посмотрим на несколько примеров.

Вызов в функции контекст будет глобальным объектом. Если вы этого не знаете, вы трагически меняете глобальный объект. Это зло.

this.creed = "Nothing is true, everything is permitted.";

function showCreed() {
    console.log(this.creed)
}

showCreed();

За исключением строгого режима. В строгом режиме он неопределен. Вы этого не знаете, на этот раз все идет не так.

"use strict"

this.creed = "Nothing is true, everything is permitted.";

function showCreed() {
    console.log(this)
}

showCreed(); // undefined

Позвоните в метод функции, контекст будет рассматриваться объект, как мы хотим. Вот почему функция «ShowTemPlarskuld» выше работает. Но не следующая вложенная функция. Следующий имеет свой собственный контекст.

showTemplarsKilled: function() {
    // this -> objet context
    console.log(`List of templar killed (${this.templarsKilled.length}) by ${this.name}`)

    this.templarsKilled.forEach(function(templarKilled) {
      // this -> function context
      console.log(`${this.name} killed ${templarKilled}`)
    });
}

Я не знаю, если вы когда-либо видели код, создайте переменные, такие как «Self» или «_This», который прошел текущий контекст? Это именно почему. Относительно отвратительный взлом, чтобы сохранить текущий контекст.

showTemplarsKilled: function() {
    const self = this;
    console.log(`List of templar killed (${self.templarsKilled.length}) by ${self.name}`)

    self.templarsKilled.forEach(function(templarKilled) {
      console.log(`${self.name} killed ${templarKilled}`)
    });
  }

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

showTemplarsKilled: function() {
    console.log(`List of templar killed (${this.templarsKilled.length}) by ${this.name}`)

    this.templarsKilled.forEach(templarKilled => console.log(`${this.name} killed ${templarKilled}`));
  }

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

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

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

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

Развертывание

Я передам различные приключения на дороге, давайте пойдем прямо к развертыванию. В этот момент я убежден, что мои вещи работают. У меня есть 3 миллиона тестов. Он работает на dev на неделю. Я бы с удовольствием ставлю на руку и две ноги.

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

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

Это явно связано с моим сервисом.

Но даже когда я искал именно в медленном коде, я не понял. Время отклика продолжало становиться дольше и дольше. Я был все больше и больше в тумане.

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

Что не так с следующим кодом?

function _load (assetFile, assetRoute) {
  return this.cdn.getFileInfo(assetFile)

  .then(assetInfo => this.setAssetInCache(JSON.Stringify(assetFile), assetInfo))

  .then(() => this.getAssetFromCache(assetRoute))

  .then(data => {
    if (data) {
      return Promise.resolve(data)
    } else {
      return Promise.reject("Can't get asset from cache.")
    }
  })

  .catch(error => Promise.reject(error))
}

Проблема в линии 5 с использованием JSON.Stringify. Это управление блокировкой. В неблокирующем асинхронном мире вы должны быть очень осторожны с такими вещами.

JSON.Stringify блокирует нить, в которой он находится. Поскольку JavaScript – это отдельная нить, это проблематично. Так что да, обещание дает задержку для блокировки. Но когда Stringify выполняется, ничего не выполняется, пока он не закончен.

Таким образом, блокируя все остальное приложение.

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

Millisecond by Millisecond, время отклика вышло до 1 секунды за звонок!

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

Это день, когда я действительно начал заинтересовать петлю мероприятия.

Как это работает, что на карту, разные фазы. От таймеров, чтобы закрыть обратный вызов к опросу ввода/вывода. Это было очень полезно на Nodejs. Но и на JavaScript вообще в браузере.

Итак, важно знать, что даже если глобальное функционирование контура событий в браузере и в Nodejs одинаково, Есть различия при масштабировании . Я говорю это, потому что у вас всегда будет самопровозглашенный «эксперт», чтобы поправить вас – с невыносимым способом, как будто это было важно.

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

Точка разрыва

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

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

Я едва упомянул встречу. Несмотря на мое обучение об услуге, этого было недостаточно, чтобы идти в ногу. Концепции и технические условия летались вокруг.

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

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

Поднимая свою игру

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

Моя рекомендация дня: Секреты JavaScript Ninja .

Эта книга является отправной точкой всей моей уверенности с JavaScript.

Объясняя меня глубоко внутренние работы, поведение на поверхности стало ясным. Мой код стал быстрым и надежным. Вопросы собеседования были легкими.

Он начинается очень тихо с тем, что происходит в браузере с JavaScript. Затем он быстро попадает в сердце вопроса с функциями. Понимание – как они работают меняет все.

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

Затем генераторы, обещания и прототипы. Наконец, он заканчивается глубоким погружением в святую петлю события, которые я наконец понял. Я вышел из Эта книга с четким видением. Готов к драке.

Итак, давайте быть понятным. Я всегда был очень честен с моими рекомендациями. Эта книга не легкая прочитанная.

Это не для вас, если вы только что начинаете JavaScript. Есть сложные моменты, где мне пришлось больше думать, читать, перечитать и посмотреть на диаграммы, чтобы действительно получить ее. Но это то, о чем эта книга.

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

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

Эпилог

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

Оригинал: “https://dev.to/jesuisundev/javascript-what-i-didn-t-understand-14hl”