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

10 лучших ошибок JavaScript из 1000+ проектов (и как их избежать)

Мы посмотрели на нашу базу данных с тысячами проектов и нашли 10 лучших ошибок в JavaScript. Мы собираемся показать вам, что вызывает их и как предотвратить их. Если вы избегаете этих “GotChas”, вы можете быть лучшим разработчиком. Tagged с JavaScript, WebDev, React.

Примечание: это было первоначально опубликовано на Блог Rollbar .

Чтобы вернуть нашему сообществу разработчиков, мы рассмотрели нашу базу данных с тысячами проектов и нашли 10 лучших ошибок в JavaScript. Мы собираемся показать вам, что вызывает их и как предотвратить их. Если вы избегаете этих «GoTchas», это сделает вас лучшим разработчиком.

Поскольку данные – King, мы собрали, проанализировали и оценили 10 лучших Javascript ошибки Анкет Rollbar собирает все ошибки для каждого проекта и суммирует, сколько раз каждый происходил. Мы делаем это, группируя ошибки в соответствии с их Отпечатки пальцев . По сути, мы группируем две ошибки, если вторая – это просто повторение первого. Это дает пользователям хороший обзор вместо ошеломляющего большого дампа, который вы увидите в файле журнала.

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

Вот 10 лучших ошибок JavaScript :

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

1. Uncaught typeerror: не может прочитать свойство

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

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

class Quiz extends Component {
  componentWillMount() {
    axios.get('/thedata').then(res => {
      this.setState({items: res.data});
    });
  }

  render() {
    return (
      
    {this.state.items.map(item =>
  • {item.name}
  • )}
); } }

Здесь есть две важные вещи:

  1. Состояние компонента (например, this.state ) начинает жизнь как неопределенное Анкет
  2. Когда вы асинхронно избираете данные, компонент будет отображаться хотя бы один раз, прежде чем загружены данные – независимо от того, извлечен ли он в конструкторе, ComponentWillMount и ComponentDidMount Анкет Когда викторина первая рендера, this.state.items не определен. Это, в свою очередь, означает Itemlist Получает предметы как неопределенные, и ты Получите ошибку – «Uncaught TypeError: не удается прочитать свойство« карта »неопределенного» в консоли.

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

class Quiz extends Component {
  // Added this:
  constructor(props) {
    super(props);

    // Assign state itself, and a default value for items
    this.state = {
      items: []
    };
  }

  componentWillMount() {
    axios.get('/thedata').then(res => {
      this.setState({items: res.data});
    });
  }

  render() {
    return (
      
    {this.state.items.map(item =>
  • {item.name}
  • )}
); } }

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

2. TypeError: «неопределенная» не является объектом (оценка

Это ошибка, которая возникает в Safari, когда вы читаете свойство или вызываете метод на неопределенном объекте. Вы можете проверить это очень легко в консоли разработчика Safari. По сути, это то же самое, что и вышеуказанная ошибка для Chrome, но Safari использует другое сообщение об ошибке.

3. TypeError: NULL не является объектом (оценка

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

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

Один из способов этой ошибки может возникнуть в примере реального мира, если вы попытаетесь использовать элемент DOM в своем JavaScript до загрузки элемента. Это потому, что DOM API возвращает NULL для ссылок на объекты, которые являются пустыми.

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

В этом примере мы можем решить проблему, добавив слушателя событий, который уведомит нас, когда страница будет готова. Однажды addEventListener уволен, init () Метод может использовать элементы DOM.



4. (неизвестно): ошибка скрипта

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

Чтобы получить реальные сообщения об ошибках, сделайте следующее:

1. Отправить заголовок для контроля доступа

Установка Access-Control-Allow-Origin Заголовок для * означает, что ресурс можно получить должным образом из любого домена. Вы можете заменить * на свой домен, если это необходимо: например, Access-Control-Allow-Origin: www.example.com Анкет Тем не менее, обработка нескольких доменов становится сложной и может не стоить усилий, если вы используете CDN из -за вопросов кэширования, которые могут возникнуть. Смотрите больше Здесь Анкет

Вот несколько примеров того, как установить этот заголовок в различных средах:

Апач

В папках, где будут поданы ваши файлы JavaScript, создайте .htaccess Файл со следующим содержанием:

Header add Access-Control-Allow-Origin "*"

Nginx

Добавьте директиву add_header в блок местоположения, который обслуживает ваши файлы JavaScript:

location ~ ^/assets/ {
    add_header Access-Control-Allow-Origin *;
}

Хапрокс

Добавьте следующее в свой бэкэнд актива, где файлы JavaScript обслуживаются:

rspadd Access-Control-Allow-Origin:\ *

2. Установить на тег скрипта

В вашем источнике HTML для каждого из сценариев вы установили Access-Control-Allow-Origin Заголовок для, установить Crossorigin = "Anonymous" На теге сценария. Убедитесь, что вы убедитесь, что заголовок отправляется для файла скрипта, прежде чем добавить Crossorigin свойство на теге сценария. В Firefox, если Crossorigin Атрибут присутствует, но Access-Control-Allow-Origin Заголовок нет, сценарий не будет выполнен.

5. TypeError: Объект не поддерживает свойство

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

Это эквивалентно ошибке «TypeError:« неопределенная »не является функцией» в Chrome. Да, разные браузеры могут иметь разные сообщения об ошибках для одной и той же логической ошибки.

Это общая проблема для IE в веб -приложениях, которые используют пространство имен JavaScript. Если это так, проблема в 99,9% случаев заключается в неспособности IE связывать методы в текущем пространстве имен с это ключевое слово. Например, если у вас есть пространство имен JS Рулона с методом это превосходно. Обычно, если вы находитесь в Рулона Пространство имен вы можете вызвать isawesome Метод со следующим синтаксисом:

this.isAwesome();

Chrome, Firefox и Opera с радостью примут этот синтаксис. Т.е., с другой стороны, не будет. Таким образом, самая безопасная ставка при использовании пространства имен JS – это всегда префикс с реальным пространством имен.

Rollbar.isAwesome();

6. TypeError: «неопределенная» не является функцией

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

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

Рассмотрим этот пример фрагмент кода:

function testFunction() {
  this.clearLocalStorage();
  this.timer = setTimeout(function() {
    this.clearBoard();    // what is "this"?
  }, 0);
};

Выполнение приведенного выше кода результаты в следующей ошибке: «Uncaught TypeError: не определяется не является функцией. “Причина, по которой вы получаете вышеуказанную ошибку, заключается в том, что когда вы вызываете setTimeout () , вы на самом деле вызываете window.settimeout () Анкет В результате анонимная функция передается в setTimeout () определяется в контексте оконного объекта, который не имеет clearboard () метод

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

function testFunction () {
  this.clearLocalStorage();
  var self = this;   // save reference to 'this', while it's still this!
  this.timer = setTimeout(function(){
    self.clearBoard();  
  }, 0);
};

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

function testFunction () {
  this.clearLocalStorage();
  this.timer = setTimeout(this.reset.bind(this), 0);  // bind to 'this'
};

function testFunction(){
    this.clearBoard();    //back in the context of the right 'this'!
};

7. Uncaught dameerror: Максимальный стек вызовов

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

Это также может произойти, если вы передадите значение функции, которая находится вне диапазона. Многие функции принимают только определенный диапазон чисел для их входных значений. Например, Number.toexponential (цифры) и n umber.tofixed (цифры) Принять цифры от 0 до 20 и Number.toprecision (цифры) принимает цифры от 1 до 21.

var a = new Array(4294967295);  //OK
var b = new Array(-1); //range error

var num = 2.555555;
document.writeln(num.toExponential(4));  //OK
document.writeln(num.toExponential(-2)); //range error!

num = 2.9999;
document.writeln(num.toFixed(2));   //OK
document.writeln(num.toFixed(25));  //range error!

num = 2.3456;
document.writeln(num.toPrecision(1));   //OK
document.writeln(num.toPrecision(22));  //range error!

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

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

var testArray= ["Test"];

function testFunction(testArray) {
    for (var i = 0; i < testArray.length; i++) {
      console.log(testArray[i]);
    }
}

testFunction();

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

У вас есть два способа решить вашу проблему:

  1. Удалить параметры в операторе объявления функции (оказывается, вы хотите получить доступ к тем переменным, которые объявляются вне функции, поэтому вам не нужны параметры для вашей функции):
   var testArray = ["Test"];

   /* Precondition: defined testArray outside of a function */
   function testFunction(/* No params */) {
       for (var i = 0; i < testArray.length; i++) {
         console.log(testArray[i]);
       }
   }

   testFunction();
  1. Вызовите функцию, передав ее массив, который мы объявили:
   var testArray = ["Test"];

   function testFunction(testArray) {
      for (var i = 0; i < testArray.length; i++) {
         console.log(testArray[i]);
       }
   }

   testFunction(testArray);

9. Uncaught typeerror: не может установить свойство

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

Например, в браузере Chrome:

Если тест Объект не существует, ошибка выбросит «Uncaught TypeError не может установить свойство неопределенного».

10. Referenceerror: событие не определено

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

Если вы получаете эту ошибку при использовании системы обработки событий, убедитесь, что вы используете объект события, переданный в качестве параметра. Старые браузеры, такие как IE, предлагают глобальное событие переменной, но оно не поддерживается во всех браузерах. Библиотеки, такие как JQuery, пытаются нормализовать это поведение. Тем не менее, наилучшим образом является использование той, которая была передана в вашу функцию обработчика событий.

function myFunction(event) {
    event = event.which || event.keyCode;
    if(event.keyCode===13){
       alert(event.keyCode);
    }
}

Вывод

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

Rollbar предлагает уникальные функции для приложений JavaScript, таких как телеметрия Что говорит вам, что произошло в браузере пользователя, ведущего к ошибке. Это понимание, которое у вас нет за пределами вашей местной консоли разработчика. Узнайте больше в полном списке Rollbar Функции для JavaScript Applications Анкет

Оригинал: “https://dev.to/mostlyjason/top-10-javascript-errors-from-1000-projects-and-how-to-avoid-them-3bkh”