Ошибка undefined это не функция

I am learning Javascript on Codecademy, and I am trying to create a function that tells me the perimeter of a rectangle. The error that has come up is:

SyntaxError: Unexpected end of input

My code is:

function Rectangle(height, width) {
  this.height = height;
  this.width = width;
};
  this.calcArea = function() {
      return this.height * this.width;
  };
  // put our perimeter function here!
  this.calcPerimeter = function() {
      return this.height * 2 + this.width * 2;
  };
var rex = new Rectangle(7,3);
var area = rex.calcArea();
var perimeter = rex.calcPerimeter();

Any help/advice greatly appreciated, thanks :)

asked Jul 1, 2014 at 12:02

Connor's user avatar

2

this.calcarea and this.calcperimeter is outside of the scope of the Rectangle. You need them to be inside the brackets of the Rectangle-object to be member-functions. Like so:

function Rectangle(height, width) {
  this.height = height;
  this.width = width;

  this.calcArea = function() {
      return this.height * this.width;
  }
  // put our perimeter function here!
  this.calcPerimeter = function() {
      return this.height * 2 + this.width * 2;
  }
}

answered Jul 1, 2014 at 12:06

bvx89's user avatar

bvx89bvx89

8685 silver badges12 bronze badges

You have close Rectangle class at wrong place.

Problem with your code is that calcPerimeter and calcArea is outside Rectangle class. So when you perform rex.calcArea(); the function in undefined.

Use

function Rectangle(height, width) {
    this.height = height;
    this.width = width;
    //}; removed from here
    this.calcArea = function () {
        return this.height * this.width;
    };
    this.calcPerimeter = function () {
        return this.height * 2 + this.width * 2;
    };
}; //Place closing brace here

var rex = new Rectangle(7, 3);
var area = rex.calcArea();
var perimeter = rex.calcPerimeter();

answered Jul 1, 2014 at 12:05

Satpal's user avatar

SatpalSatpal

132k13 gold badges158 silver badges167 bronze badges

You’ll Need To use

Rectangle.prototype, as follows:

function Rectangle(height, width) {
  this.height = height;
  this.width = width;
}
Rectangle.prototype.calcArea = function() {
      return this.height * this.width;
};
Rectangle.prototype.calcPerimeter = function() {
      return this.height * 2 + this.width * 2;
  };
var rex = new Rectangle(7,3);
var area = rex.calcArea();
var perimeter = rex.calcPerimeter();

That’ll create a Method for class Rectangle.

In your code Your Methods area() and perimeter are referring to this object, which in this case is pointing to window. So it is of no use. To make this point to Rectangles Object. You need to use Rectangle.prototype.methodName=function(){//Here this =Rectangle Obj };

className.prototype.methodName

in javascript creates public methods(methodName) which can be accessible by the objects of that class.

DEMO.

Hope it Helps! :)!

answered Jul 1, 2014 at 12:09

Vedant Terkar's user avatar

Vedant TerkarVedant Terkar

4,5158 gold badges36 silver badges61 bronze badges

undefined в JavaScript — настоящий кошмар начинающего фронтендера. В чём отличие undefined и null, если даже сравнение null == undefined выводит true, и как обрабатывать ошибку undefined? Давайте разбираться.

Примечание Вы читаете улучшенную версию некогда выпущенной нами статьи.

  1. Что такое undefined в JavaScript
  2. Как избежать undefined в JavaScript
  3. Значение undefined в массивах
  4. Отличие null и undefined в JavaScript
  5. Заключение

undefined является специальным значением. Согласно спецификации ECMAScript, undefined в JavaScript можно получить при доступе к неинициализированным переменным, несуществующим свойствам объекта, несуществующим элементам массива, etc. Пример:

let number;  
number;     // => undefined  
let movie = { name: 'Interstellar' };  
movie.year; // => undefined  
let movies = ['Interstellar', 'Alexander'];  
movies[3];  // => undefined

Как видим, undefined выводится при попытке доступа к:

  • неинициализированной переменной number;
  • несуществующему свойству объекта movie.year;
  • несуществующему элементу массива movies[3].

Оператор typeof возвращает строку undefined для неопределённого значения:

typeof undefined === 'undefined'; // => true

Оператор typeof отлично подходит для проверки значения undefined в JavaScript:

let nothing;  
typeof nothing === 'undefined';   // => true

Как избежать undefined в JavaScript

Неинициализированная переменная

Объявленная переменная, которая еще не имеет значения (не инициализирована), по умолчанию undefined. Пример:

let myVariable;  
myVariable; // => undefined

Переменная myVariable уже объявлена, но ещё не имеет присвоенного значения. Попытка обратиться к ней закончится выводом undefined. Чтобы это исправить, достаточно присвоить переменной значение. Чем меньше переменная существует в неинициализированном состоянии, тем лучше.

Ниже приведены способы решения проблемы.

1. const и let вместо var

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

При использовании неизменяемых данных (констант) рекомендуется инициализировать их как const:

const myVariable = 'initial'

Константа не подвергается неинициализированному состоянию, и получить значение undefined  в этом случае невозможно.

Если вам нужно менять значение переменной, то обозначьте её как let и также присваивайте ей начальное значение:

let index = 0

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

function bigFunction() {  
  // код...
  myVariable; // => undefined
  // код...
  var myVariable = 'Initial value';
  // код...
  myVariable; // => 'Initial value'
}
bigFunction();

В этом случае переменная myVariable содержит undefined до получения значения:

myVariable = 'Initial value'

Если же переменную объявить как let, она останется недоступной до момента присвоения ей значения. Таким образом, использование const или let снизит риск получения значения undefined в JavaScript.

2. Усиление связности

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

  • сфокусированным и понятным;
  • легко поддерживаемым и поддающимся рефакторингу;
  • многоразовым;
  • простым для тестирования.

undefined в JavaScript и связность

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

Вот классический пример того, как не надо делать:

function someFunc(array) {  
  var index, item, length = array.length;
  // некоторый код...
  // некоторый код...
  for (index = 0; index < length; index++) {
    item = array[index];
    // некоторый код...
  }
  return 'some result';
}

index, item и length объявляются в начале функции, но используются они лишь ближе к концу. Всё время между объявлением переменной в начале и до использования её в цикле index и item не инициализируются и выводят undefined. Разумнее переместить переменные ближе к месту их применения:

function someFunc(array) {  
  // некоторый код...
  // некоторый код...
  const length = array.length;
  for (let index = 0; index < length; index++) {
    const item = array[index];
    // некоторый код 
  }
  return 'some result';
}

Доступ к несуществующему свойству

Попытка получить доступ к несуществующему свойству объекта JavaScript заканчивается undefined. Пример:

let favoriteMovie = {  
  title: 'Blade Runner'
};
favoriteMovie.actors; // => undefined

favoriteMovie — объект с одним значением title. Доступ к несуществующему свойству actors приведёт к выводу undefined.

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

TypeError: Cannot read property <prop> of undefined

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

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

Реализуем функцию append(array, toAppend), которая добавляет в начале и/или в конце массива новые элементы:

function append(array, toAppend) {  
  const arrayCopy = array.slice();
  if (toAppend.first) {
    arrayCopy.unshift(toAppend.first);
  }
  if (toAppend.last) {
    arrayCopy.push(toAppend.last);
  }
  return arrayCopy;
}
append([2, 3, 4], { first: 1, last: 5 }); // => [1, 2, 3, 4, 5]  
append(['Hello'], { last: 'World' });     // => ['Hello', 'World']  
append([8, 16], { first: 4 });            // => [4, 8, 16]

Поскольку объект toAppend может удалять первые или последние свойства, необходимо проверить их существование с помощью условий if(toAppend.first){} и if(toAppend.last){}.

Вот только undefined, как false, null, 0, NaN и ' ', является ложными значением, а в текущей реализации функция append() не позволяет вставлять ложные элементы:

append([10], { first: 0, last: false }); // => [10]

0 и false — ложные значения, потому что if (toAppend.first){} и if (toAppend.last){} фактически сравниваются с ложными значениями, и эти элементы не вставляются в массив. Функция возвращает исходный массив [10] без изменений.

1. Наличие свойства

К счастью, JavaScript предлагает множество способов определить, имеет ли объект определённое свойство:

  • obj.prop !== undefined в JavaScript позволяет проверить undefined, сравнив с ним объект;
  • typeof obj.prop !== 'undefined' проверяет тип значения свойства;
  • obj.hasOwnProperty('prop') проверяет объект на наличие собственного свойства;
  • 'prop' in obj проверяет объект на наличие собственного или унаследованного свойства.

Рекомендацией в этом случае будет использование оператора in , чтобы проверить, имеет ли объект определённое свойство, не обращаясь к фактическому значению этого свойства:

function append(array, toAppend) {  
  const arrayCopy = array.slice();
  if ('first' in toAppend) {
    arrayCopy.unshift(toAppend.first);
  }
  if ('last' in toAppend) {
    arrayCopy.push(toAppend.last);
  }
  return arrayCopy;
}
append([2, 3, 4], { first: 1, last: 5 }); // => [1, 2, 3, 4, 5]  
append([10], { first: 0, last: false });  // => [0, 10, false]

'first' in toAppend ( как и 'last' in toAppend) выводит true, независимо от существующего свойства. В других случаях выводится — false.

Использование оператора in устраняет проблему со вставкой ложных элементов 0 и false. Теперь добавление элементов в начале и в конце массива [10] приводит к ожидаемому результату: [0, 10, false].

2. Деструктуризация доступа к свойствам объекта

Деструктуризация объекта позволяет устанавливать значение по умолчанию, если свойство не существует: удобно для исключения прямого контакта с undefined:

const object = { };  
const { prop = 'default' } = object;  
prop; // => 'default'

Применяя преимущества деструктуризации объекта, реализуем quote():

function quote(str, config) {  
  const { char = '"', skipIfQuoted = true } = config;
  const length = str.length;
  if (skipIfQuoted
      && str[0] === char
      && str[length - 1] === char) {
    return str;
  }
  return char + str + char;
}
quote('Hello World', { char: '*' });        // => '*Hello World*'  
quote('"Welcome"', { skipIfQuoted: true }); // => '"Welcome"'

const { char = '"', skipIfQuoted = true } = config в одной строкe извлекает свойства char и skipIfQuoted из объекта config.

Если некоторые свойства недоступны в объекте config,  деструктуризация задаёт значения по умолчанию: '"' для char и false для skipIfQuoted. К счастью, функцию можно улучшить.

Переместим деструктуризацию в раздел параметров и установим значение по умолчанию (пустой объект { }) для параметра config, чтобы пропустить второй аргумент, когда будет достаточно значений по умолчанию:

function quote(str, { char = '"', skipIfQuoted = true } = {}) {  
  const length = str.length;
  if (skipIfQuoted
      && str[0] === char
      && str[length - 1] === char) {
    return str;
  }
  return char + str + char;
}
quote('Hello World', { char: '*' }); // => '*Hello World*'  
quote('Sunny day');                  // => '"Sunny day"'

Деструктурирующее присваивание гарантирует, что используется пустой объект, если второй аргумент не указан вообще. В результате вы избегаете возникновения значения undefined в JavaScript.

3. Свойство по умолчанию

Есть простой способ установить значения по умолчанию для свойств объекта, и имя ему Spread syntax:

const unsafeOptions = {  
  fontSize: 18
};
const defaults = {  
  fontSize: 16,
  color: 'black'
};
const options = {  
  ...defaults,
  ...unsafeOptions
};
options.fontSize; // => 18  
options.color;    // => 'black'

Инициализатор объекта распространяет свойства из исходных объектов defaults и unsafeOptions. Важен порядок, в котором указаны исходные объекты: свойства более позднего исходного объекта перезаписывают более ранние. Независимо от ситуации, объект всегда содержит полный набор свойств, и появление undefined невозможно.

Параметры функции

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

function multiply(a, b) {  
  a; // => 5
  b; // => 3
  return a * b;
}
multiply(5, 3); // => 15

При вызове функции multiply(5, 3) параметры a и b получают соответствующие значения 5 и 3. Умножение рассчитывается как ожидаемое: 5 * 3 = 15.

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

Лучшим подходом является использование параметров по умолчанию из ES2015:

function multiply(a, b = 2) {  
  a; // => 5
  b; // => 2
  return a * b;
}
multiply(5);            // => 10  
multiply(5, undefined); // => 10

Значение b = 2 в сигнатуре функции гарантирует, что если b получит значение undefined, то по умолчанию параметр изменится на 2.

Возвращаемое значение функции

В JavaScript функция, которая не имеет оператора return, возвращает значение undefined:

function square(x) {  
  const res = x * x;
}
square(2); // => undefined

То же происходит, если return присутствует, но без какого-либо выражения рядом:

function square(x) {  
  const res = x * x;
  return;
}
square(2); // => undefined

Указывая значение для return, можно получить желаемый результат:

function square(x) {  
  const res = x * x;
  return res;
}
square(2); // => 4

Теперь вызов функции выведет нужное значение.

Оператор void

Оператор void выполняет выражение и возвращает undefined вне зависимости от результата:

void 1;                    // => undefined  
void (false);              // => undefined  
void {name: 'John Smith'}; // => undefined  
void Math.min(1, 3);       // => undefined

Одним из вариантов использования оператора void является переопределение результата выполнения выражения и возврат undefined в случае возникновения неожиданных результатов выполнения функции.

Значение undefined в массивах

Вы получаете undefined при попытке доступа к элементу массива с индексом вне пределов массива.

const colors = ['blue', 'white', 'red'];  
colors[5];  // => undefined  
colors[-1]; // => undefined

Массив colors имеет 3 элемента, поэтому корректные индексы равны 0, 1 и 2. Поскольку в индексах массива 5 и -1 нет элементов, значения colors[5] и colors[-1] получают значение undefined.

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

const sparse1 = new Array(3);  
sparse1;       // => [<empty slot>, <empty slot>, <empty slot>]  
sparse1[0];    // => undefined  
sparse1[1];    // => undefined  
const sparse2 = ['white',  ,'blue']  
sparse2;       // => ['white', <empty slot>, 'blue']  
sparse2[1];    // => undefined

sparse1 создается путем вызова конструктора Array с числовым первым аргументом. Он имеет 3 пустых элемента. sparse2 создается с литералом массива, второй элемент которого отсутствует. В любом из этих массивов доступ к пустому элементу оценивается как undefined.

Отличие null и undefined в JavaScript

Основное отличие в том, что undefined представляет значение переменной, которая ещё не была инициализирована, а null — намеренное отсутствие объекта.

Допустим, переменная number определена, но ей не назначено начальное значение:

let number;  
number; // => undefined

То же самое произойдёт при попытке доступа к несуществующему свойству объекта:

const obj = { firstName: 'Dmitri' };  
obj.lastName; // => undefined

Или переменная должна ожидать возвращение объекта функции, но по какой-то причине создание объекта невозможно. В этом случае null является значимым индикатором недостающего объекта. Например, clone() — это функция, которая клонирует простой объект JavaScript. Ожидается, что функция вернёт объект:

function clone(obj) {  
  if (typeof obj === 'object' && obj !== null) {
    return Object.assign({}, obj);
  }
  return null;
}
clone({name: 'John'}); // => {name: 'John'}  
clone(15);             // => null  
clone(null);           // => null

Но clone() может быть вызван с пустым аргументом: 15 или null. В этом случае функция не может создать клон, поэтому возвращает null — индикатор отсутствующего объекта.

В JavaScript существуют проверки на null и undefined. Оператор typeof демонстрирует различие между двумя значениями:

typeof undefined; // => 'undefined'  
typeof null;      // => 'object'

Строгий оператор равенства === также отличает undefined от null:

let nothing = undefined;  
let missingObject = null;  
nothing === missingObject; // => false

Вам также может быть интересна наша статья про обработку ошибок в JavaScript.

Заключение 

Стратегия борьбы с undefined в JavaScript:

  1. Уменьшить использование неинициализированных переменных.
  2. Сделать жизненный цикл переменных коротким и близким к источнику их использования.
  3. Назначить начальное значение переменным.
  4. Использовать const или let.
  5. Проверять наличие свойств или заполнить небезопасные объекты по умолчанию.
  6. Использовать значения по умолчанию для некритичных параметров функции.
  7. Избегать использования разрежённых массивов.

Перевод статьи «7 tips to handle undefined in JavaScript»

JavaScript может быть кошмаром при отладке: некоторые ошибки, которые он выдает, могут быть очень трудны для понимания с первого взгляда, и выдаваемые номера строк также не всегда полезны. Разве не было бы полезно иметь список, глядя на который, можно понять смысл ошибок и как исправить их? Вот он!

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

Как читать ошибки?

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

Типичная ошибка из Chrome выглядит так:

Uncaught TypeError: undefined is not a function

Структура ошибки следующая:

  1. Uncaught TypeError: эта часть сообщения обычно не особо полезна. Uncaught значит, что ошибка не была перехвачена в catch, а TypeError — это название ошибки.
  2. undefined is not a function: это та самая часть про ошибку. В случае с сообщениями об ошибках, читать их нужно прямо буквально. Например, в этом случае, она значит то, что код попытался использовать значение undefined как функцию.

Другие webkit-браузеры, такие как Safari, выдают ошибки примерно в таком же формате, как и Chrome. Ошибки из Firefox похожи, но не всегда включают в себя первую часть, и последние версии Internet Explorer также выдают более простые ошибки, но в этом случае проще — не всегда значит лучше.

Теперь к самим ошибкам.

Uncaught TypeError: undefined is not a function

Связанные ошибки: number is not a function, object is not a function, string is not a function, Unhandled Error: ‘foo’ is not a function, Function Expected

Возникает при попытке вызова значения как функции, когда значение функцией не является. Например:

var foo = undefined;
foo();

Эта ошибка обычно возникает, если вы пытаетесь вызвать функцию для объекта, но опечатались в названии.

var x = document.getElementByID('foo');

Несуществующие свойства объекта по-умолчанию имеют значение undefined, что приводит к этой ошибке.

Другие вариации, такие как “number is not a function” возникают при попытке вызвать число, как будто оно является функцией.

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

Uncaught ReferenceError: Invalid left-hand side in assignment

Связанные ошибки: Uncaught exception: ReferenceError: Cannot assign to ‘functionCall()’, Uncaught exception: ReferenceError: Cannot assign to ‘this’

Вызвано попыткой присвоить значение тому, чему невозможно присвоить значение.

Наиболее частый пример этой ошибки — это условие в if:

if(doSomething() = 'somevalue')

В этом примере программист случайно использовал один знак равенства вместо двух. Выражение “left-hand side in assignment” относится к левой части знака равенства, а, как можно видеть в данном примере, левая часть содержит что-то, чему нельзя присвоить значение, что и приводит к ошибке.

Как исправить ошибку: убедитесь, что вы не пытаетесь присвоить значение результату функции или ключевому слову this.

Uncaught TypeError: Converting circular structure to JSON

Связанные ошибки: Uncaught exception: TypeError: JSON.stringify: Not an acyclic Object, TypeError: cyclic object value, Circular reference in value argument not supported

Всегда вызвано циклической ссылкой в объекте, которая потом передается в JSON.stringify.

var a = { };
var b = { a: a };
a.b = b;
JSON.stringify(a);

Так как a и b в примере выше имеют ссылки друг на друга, результирующий объект не может быть приведен к JSON.

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

Unexpected token ;

Связанные ошибки: Expected ), missing ) after argument list

Интерпретатор JavaScript что-то ожидал, но не обнаружил там этого. Обычно вызвано пропущенными фигурными, круглыми или квадратными скобками.

Токен в данной ошибке может быть разным — может быть написано “Unexpected token ]”, “Expected {” или что-то еще.

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

Ошибка с [ ] { } ( ) обычно вызвано несовпадающей парой. Проверьте, все ли ваши скобки имеют закрывающую пару. В этом случае, номер строки обычно указывает на что-то другое, а не на проблемный символ.

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

Unexpected; обычно вызвано символом; внутри литерала объекта или массива, или списка аргументов вызова функции. Номер строки обычно также будет верным для данного случая.

Uncaught SyntaxError: Unexpected token ILLEGAL

Связанные ошибки: Unterminated String Literal, Invalid Line Terminator

В строковом литерале пропущена закрывающая кавычка.

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

Uncaught TypeError: Cannot read property ‘foo’ of null, Uncaught TypeError: Cannot read property ‘foo’ of undefined

Связанные ошибки: TypeError: someVal is null, Unable to get property ‘foo’ of undefined or null reference

Попытка прочитать null или undefined так, как будто это объект. Например:

var someVal = null;
console.log(someVal.foo);

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

Uncaught TypeError: Cannot set property ‘foo’ of null, Uncaught TypeError: Cannot set property ‘foo’ of undefined

Связанные ошибки: TypeError: someVal is undefined, Unable to set property ‘foo’ of undefined or null reference

Попытка записать null или undefined так, как будто это объект. Например:

var someVal = null;
someVal.foo = 1;

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

Uncaught RangeError: Maximum call stack size exceeded

Связанные ошибки: Uncaught exception: RangeError: Maximum recursion depth exceeded, too much recursion, Stack overflow

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

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

Uncaught URIError: URI malformed

Связанные ошибки: URIError: malformed URI sequence

Вызвано некорректным вызовом decodeURIComponent.

Как исправить ошибку: убедитесь, что вызовы decodeURIComponent на строке ошибки получают корректные входные данные.

XMLHttpRequest cannot load some/url. No ‘Access-Control-Allow-Origin’ header is present on the requested resource

Связанные ошибки: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at some/url

Эта проблема всегда связана с использованием XMLHttpRequest.

Как исправить ошибку: убедитесь в корректности запрашиваемого URL и в том, что он удовлетворяет same-origin policy. Хороший способ найти проблемный код — посмотреть на URL в сообщении ошибки и найти его в своём коде.

InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable

Связанные ошибки: InvalidStateError, DOMException code 11

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

var xhr = new XMLHttpRequest();
xhr.setRequestHeader('Some-Header', 'val');

В данном случае вы получите ошибку потому, что функция setRequestHeader может быть вызвана только после вызова xhr.open.

Как исправить ошибку: посмотрите на код в строке, указывающей на ошибку, и убедитесь, что он вызывается в правильный момент или добавляет нужные вызовы до этого (как с xhr.open).

Заключение

JavaScript содержит в себе одни из самых бесполезных ошибок, которые я когда-либо видел, за исключением печально известной Expected T_PAAMAYIM_NEKUDOTAYIM в PHP. Большая ознакомленность с ошибками привносит больше ясности. Современные браузеры тоже помогают, так как больше не выдают абсолютно бесполезные ошибки, как это было раньше.

Какие самые непонятные ошибки вы встречали? Делитесь своими наблюдениями в комментариях.

P.S. Этот перевод можно улучшить, отправив PR здесь.

Google Chrome, JavaScript


Рекомендация: подборка платных и бесплатных курсов JavaScript — https://katalog-kursov.ru/

Джаваскриптовая ошибка «undefined is not a function» довольно загадочна. Как раз поэтому определённым спросом пользуются разъяснительные статьи, из которых читатель, начинающий изучать программирование на JavaScript, способен узнать о том, что такая ошибка (попытка использовать неопределённое значение как функцию) чаще всего возникает при вызове несуществующего метода объекта (а такой вызов, в свою очередь, чаще всего происходит в случае опечатки в названии метода). Такой разъяснительной статьёю может послужить «Ошибки в JavaScript и как их исправить», например.

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

Так и вышло:

Improved exception messages: Goodbye «undefined is not a function». Hello «http://t.co/rMIELG5VoW is not a function» pic.twitter.com/3uykfrTK9O

— Addy Osmani (@addyosmani) 21 февраля 2015

Впрочем, вышеозначенное улучшение сообщения об ошибке произошло только в V8, то есть появится оно только в Google Chrome, в Chromium, в новой Опере, а со временем — в Node.js и в других нодоподобных движках, служащих для запуска внебраузерного джаваскрипта. О внедрении подобного улучшения в остальных браузерах ничего не известно.

Uncaught TypeError: undefined is not a function example_app.js:7

This error message tells the whole story. On this line, you are trying to execute a function. However, whatever is being executed is not a function! Instead, it’s undefined.

So what’s on example_app.js line 7? Looks like this:

var tasks = new ExampleApp.Collections.Tasks(data.tasks);

There is only one function being run on that line. We found the problem! ExampleApp.Collections.Tasks is undefined.

So lets look at where that is declared:

var Tasks = Backbone.Collection.extend({
    model: Task,
    url: '/tasks'
});

If that’s all the code for this collection, then the root cause is right here. You assign the constructor to global variable, called Tasks. But you never add it to the ExampleApp.Collections object, a place you later expect it to be.

Change that to this, and I bet you’d be good.

ExampleApp.Collections.Tasks = Backbone.Collection.extend({
    model: Task,
    url: '/tasks'
});

See how important the proper names and line numbers are in figuring this out? Never ever regard errors as binary (it works or it doesn’t). Instead read the error, in most cases the error message itself gives you the critical clues you need to trace through to find the real issue.


In Javascript, when you execute a function, it’s evaluated like:

expression.that('returns').aFunctionObject(); // js
execute -> expression.that('returns').aFunctionObject // what the JS engine does

That expression can be complex. So when you see undefined is not a function it means that expression did not return a function object. So you have to figure out why what you are trying to execute isn’t a function.

And in this case, it was because you didn’t put something where you thought you did.

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

От автора: чтобы вернуть сообщество разработчиков, мы рассмотрели нашу базу данных по тысячам проектов и нашли 10 самых распространённых ошибок в JavaScript. Мы собираемся показать вам, что к ним приводит и как это предотвратить. Если ни одна ошибка JavaScript не встречается в вашем коде, это делает вас лучшим разработчиком.

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

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

Вот первые 10 ошибок JavaScript:

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

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

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

1. Uncaught TypeError: Cannot read property

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

class Quiz extends Component {

  componentWillMount() {

    axios.get(‘/thedata’).then(res => {

      this.setState({items: res.data});

    });

  }

  render() {

    return (

      <ul>

        {this.state.items.map(item =>

          <li key={item.id}>{item.name}</li>

        )}

      </ul>

    );

  }

}

Здесь понимаются две важные вещи:

Состояние компонента (например, this.state ) начинает жизнь как undefined.

Когда вы извлекаете данные асинхронно, компонент будет отображаться как минимум один раз перед загрузкой данных — независимо от того, выбрана ли она в конструкторе componentWillMount или componentDidMount . Когда Quiz отображается впервые, this.state.items не определен. Это, в свою очередь, означает, что ItemList получает элементы как неопределенные, и вы получаете сообщение об ошибке «Uncaught TypeError: Невозможно прочитать карту свойств» в консоли.

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

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 (

      <ul>

        {this.state.items.map(item =>

          <li key={item.id}>{item.name}</li>

        )}

      </ul>

    );

  }

}

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

2. TypeError: ‘undefined’ is not an object (evaluating

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

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

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

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

1. Uncaught TypeError: Cannot read property

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

class Quiz extends Component {

  componentWillMount() {

    axios.get(‘/thedata’).then(res => {

      this.setState({items: res.data});

    });

  }

  render() {

    return (

      <ul>

        {this.state.items.map(item =>

          <li key={item.id}>{item.name}</li>

        )}

      </ul>

    );

  }

}

Здесь понимаются две важные вещи:

Состояние компонента (например, this.state ) начинает жизнь как undefined.

Когда вы извлекаете данные асинхронно, компонент будет отображаться как минимум один раз перед загрузкой данных — независимо от того, выбрана ли она в конструкторе componentWillMount или componentDidMount . Когда Quiz отображается впервые, this.state.items не определен. Это, в свою очередь, означает, что ItemList получает элементы как неопределенные, и вы получаете сообщение об ошибке «Uncaught TypeError: Невозможно прочитать карту свойств» в консоли.

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

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 (

      <ul>

        {this.state.items.map(item =>

          <li key={item.id}>{item.name}</li>

        )}

      </ul>

    );

  }

}

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

2. TypeError: ‘undefined’ is not an object (evaluating

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

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

3. TypeError: null is not an object (evaluating

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

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

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

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

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<script>

  function init() {

    var myButton = document.getElementById(«myButton»);

    var myTextfield = document.getElementById(«myTextfield»);

    myButton.onclick = function() {

      var userName = myTextfield.value;

    }

  }

  document.addEventListener(‘readystatechange’, function() {

    if (document.readyState === «complete») {

      init();

    }

  });

</script>

<form>

  <input type=«text» id=«myTextfield» placeholder=«Type your name» />

  <input type=«button» id=«myButton» value=«Go» />

</form>

4. (unknown): Script error

Ошибка скрипта возникает, когда ошибка неперехваченного JavaScript пересекает границы домена и нарушает политику перекрестного происхождения. Например, если вы размещаете свой код JavaScript на CDN, любые неперехваченные ошибки (ошибки, которые появляются в обработчике window.onerror, вместо того, чтобы быть пойманным в try-catch) будут переданы как просто «Script error» вместо того, чтобы содержать полезную информацию. Эта мера безопасности браузера предназначена для предотвращения передачи данных по доменам, которые в противном случае не были бы допущены к коммуникации.

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

1. Отправьте заголовок Access-Control-Allow-Origin

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

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

Apache

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

Header add AccessControlAllowOrigin «*»

Nginx

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

location ~ ^/assets/ { add_header AccessControlAllowOrigin *; }

HAProxy

Добавьте в ресурс, где будут загружены файлы JavaScript:

rspadd AccessControlAllowOrigin: *

2. Установите crossorigin = «anonymous» в теге скрипта

В HTML-источнике для каждого из сценариев, где вы установите заголовок Access-Control-Allow-Origin, в теге SCRIPT установите crossorigin=»anonymous». Убедитесь, что заголовок отправляется для файла сценария, перед добавлением свойства crossorigin в тег скрипта. В Firefox, если атрибут crossorigin присутствует, но заголовок Access-Control-Allow-Origin отсутствует, сценарий не будет выполнен.

5. TypeError: Object doesn’t support property

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

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

Это эквивалентно ошибке «TypeError: ‘undefined’ is not a function» в Chrome. Да, разные браузеры могут иметь разные сообщения для одной и той же ошибки.

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

Это обычная проблема для IE в веб-приложениях, использующих пространство имен JavaScript. Когда это так, проблема в 99,9% случаев— это неспособность IE связать методы в текущем пространстве имен с ключевым словом this. Например, если у вас есть пространство имен имен Rollbar с помощью метода isAwesome. Обычно, если вы находитесь в пространстве имен Rollbar вы можете вызвать метод isAwesome со следующим синтаксисом:

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

6. TypeError: ‘undefined’ is not a function

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

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

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

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

function clearBoard(){

  alert(«Cleared»);

}

document.addEventListener(«click», function(){

  this.clearBoard(); // what is “this” ?

});

Выполнение вышеуказанного кода приводит к следующей ошибке: «Uncaught TypeError: undefined is not function». Причина, по которой вы получаете эту ошибку, заключается в том, что при вызове setTimeout() вы вызываете window.setTimeout(). В результате анонимная функция, передаваемая setTimeout(), определяется в контексте объекта окна, у которого нет clearBoard().

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

var self=this;  // save reference to ‘this’, while it’s still this!

document.addEventListener(«click», function(){

  self.clearBoard();

});

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

document.addEventListener(«click»,this.clearBoard.bind(this));

7. Uncaught RangeError: Maximum call stack

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

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

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<script>

  function init() {

    var myButton = document.getElementById(«myButton»);

    var myTextfield = document.getElementById(«myTextfield»);

    myButton.onclick = function() {

      var userName = myTextfield.value;

    }

  }

  document.addEventListener(‘readystatechange’, function() {

    if (document.readyState === «complete») {

      init();

    }

  });

</script>

<form>

  <input type=«text» id=«myTextfield» placeholder=«Type your name» />

  <input type=«button» id=«myButton» value=«Go» />

</form>

4. (unknown): Script error

Ошибка скрипта возникает, когда ошибка неперехваченного JavaScript пересекает границы домена и нарушает политику перекрестного происхождения. Например, если вы размещаете свой код JavaScript на CDN, любые неперехваченные ошибки (ошибки, которые появляются в обработчике window.onerror, вместо того, чтобы быть пойманным в try-catch) будут переданы как просто «Script error» вместо того, чтобы содержать полезную информацию. Эта мера безопасности браузера предназначена для предотвращения передачи данных по доменам, которые в противном случае не были бы допущены к коммуникации.

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

1. Отправьте заголовок Access-Control-Allow-Origin

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

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

Apache

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

Header add AccessControlAllowOrigin «*»

Nginx

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

location ~ ^/assets/ { add_header AccessControlAllowOrigin *; }

HAProxy

Добавьте в ресурс, где будут загружены файлы JavaScript:

rspadd AccessControlAllowOrigin: *

2. Установите crossorigin = «anonymous» в теге скрипта

В HTML-источнике для каждого из сценариев, где вы установите заголовок Access-Control-Allow-Origin, в теге SCRIPT установите crossorigin=»anonymous». Убедитесь, что заголовок отправляется для файла сценария, перед добавлением свойства crossorigin в тег скрипта. В Firefox, если атрибут crossorigin присутствует, но заголовок Access-Control-Allow-Origin отсутствует, сценарий не будет выполнен.

5. TypeError: Object doesn’t support property

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

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

Это эквивалентно ошибке «TypeError: ‘undefined’ is not a function» в Chrome. Да, разные браузеры могут иметь разные сообщения для одной и той же ошибки.

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

Это обычная проблема для IE в веб-приложениях, использующих пространство имен JavaScript. Когда это так, проблема в 99,9% случаев— это неспособность IE связать методы в текущем пространстве имен с ключевым словом this. Например, если у вас есть пространство имен имен Rollbar с помощью метода isAwesome. Обычно, если вы находитесь в пространстве имен Rollbar вы можете вызвать метод isAwesome со следующим синтаксисом:

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

6. TypeError: ‘undefined’ is not a function

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

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

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

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

function clearBoard(){

  alert(«Cleared»);

}

document.addEventListener(«click», function(){

  this.clearBoard(); // what is “this” ?

});

Выполнение вышеуказанного кода приводит к следующей ошибке: «Uncaught TypeError: undefined is not function». Причина, по которой вы получаете эту ошибку, заключается в том, что при вызове setTimeout() вы вызываете window.setTimeout(). В результате анонимная функция, передаваемая setTimeout(), определяется в контексте объекта окна, у которого нет clearBoard().

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

var self=this;  // save reference to ‘this’, while it’s still this!

document.addEventListener(«click», function(){

  self.clearBoard();

});

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

document.addEventListener(«click»,this.clearBoard.bind(this));

7. Uncaught RangeError: Maximum call stack

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

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

Это также может произойти, если вы передадите значение функции, находящейся за пределами допустимого диапазона. Многие функции принимают только определенный диапазон чисел для своих входных значений. Например, Number.toExponential(digits) и N umber.toFixed(digits) принимают цифры от 0 до 20, а Number.toPrecision(digits) принимают цифры от 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!

8. TypeError: Cannot read property ‘length’

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

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

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

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();

2. Вызовите функцию, передав ей массив, который мы объявили:

var testArray = [«Test»];

function testFunction(testArray) {

   for (var i = 0; i < testArray.length; i++) {

      console.log(testArray[i]);

    }

}

testFunction(testArray);

9. Uncaught TypeError: Cannot set property

Когда мы пытаемся получить доступ к неопределенной переменной, она всегда возвращает undefined, а мы не можем получить или установить любое свойство undefined. В этом случае приложение будет выбрасывать “Uncaught TypeError cannot set property of undefined.”

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

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

Если объект test не существует, будет выдаваться ошибка: “Uncaught TypeError cannot set property of undefined.”

10. ReferenceError: event is not defined

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

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

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

document.addEventListener(«mousemove», function (event) {

  console.log(event);

})

Вывод

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

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

Автор: Jason Skowronski

Источник: //rollbar.com/

Редакция: Команда webformyself.

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Смотреть

JavaScript can be a nightmare to debug: Some errors it gives can be very difficult to understand at first, and the line numbers given aren’t always helpful either. Wouldn’t it be useful to have a list where you could look to find out what they mean and how to fix them? Here you go!

Below is a list of the strange errors in JavaScript. Different browsers can give you different messages for the same error, so there are several different examples where applicable.

How to read errors?

Before the list, let’s quickly look at the structure of an error message. Understanding the structure helps understand the errors, and you’ll have less trouble if you run into any errors not listed here.

A typical error from Chrome looks like this:

Uncaught TypeError: undefined is not a function

The structure of the error is as follows:

  1. Uncaught TypeError: This part of the message is usually not very useful. Uncaught means the error was not caught in a catch statement, and TypeError is the error’s name.
  2. undefined is not a function: This is the message part. With error messages, you have to read them very literally. For example in this case it literally means that the code attempted to use undefined like it was a function.

Other webkit-based browsers, like Safari, give errors in a similar format to Chrome. Errors from Firefox are similar, but do not always include the first part, and recent versions of Internet Explorer also give simpler errors than Chrome – but in this case, simpler does not always mean better.

Now onto the actual errors.

Uncaught TypeError: undefined is not a function

Related errors: number is not a function, object is not a function, string is not a function, Unhandled Error: ‘foo’ is not a function, Function Expected

Occurs when attempting to call a value like a function, where the value is not a function. For example:

var foo = undefined;
foo();

This error typically occurs if you are trying to call a function in an object, but you typed the name wrong.

var x = document.getElementByID('foo');

Since object properties that don’t exist are undefined by default, the above would result in this error.

The other variations such as “number is not a function” occur when attempting to call a number like it was a function.

How to fix this error: Ensure the function name is correct. With this error, the line number will usually point at the correct location.

Uncaught ReferenceError: Invalid left-hand side in assignment

Related errors: Uncaught exception: ReferenceError: Cannot assign to ‘functionCall()’, Uncaught exception: ReferenceError: Cannot assign to ‘this’

Caused by attempting to assign a value to something that cannot be assigned to.

The most common example of this error is with if-clauses:

if(doSomething() = 'somevalue')

In this example, the programmer accidentally used a single equals instead of two. The message “left-hand side in assignment” is referring to the part on the left side of the equals sign, so like you can see in the above example, the left-hand side contains something you can’t assign to, leading to the error.

How to fix this error: Make sure you’re not attempting to assign values to function results or to the this keyword.

Uncaught TypeError: Converting circular structure to JSON

Related errors: Uncaught exception: TypeError: JSON.stringify: Not an acyclic Object, TypeError: cyclic object value, Circular reference in value argument not supported

Always caused by a circular reference in an object, which is then passed into JSON.stringify.

var a = { };
var b = { a: a };
a.b = b;
JSON.stringify(a);

Because both a and b in the above example have a reference to each other, the resulting object cannot be converted into JSON.

How to fix this error: Remove circular references like in the example from any objects you want to convert into JSON.

Unexpected token ;

Related errors: Expected ), missing ) after argument list

The JavaScript interpreter expected something, but it wasn’t there. Typically caused by mismatched parentheses or brackets.

The token in this error can vary – it might say “Unexpected token ]” or “Expected {” etc.

How to fix this error: Sometimes the line number with this error doesn’t point to the correct place, making it difficult to fix.

  • An error with [ ] { } ( ) is usually caused by a mismatching pair. Check that all your parentheses and brackets have a matching pair. In this case, line number will often point to something else than the problem character
  • Unexpected / is related to regular expressions. The line number for this will usually be correct.
  • Unexpected ; is usually caused by having a ; inside an object or array literal, or within the argument list of a function call. The line number will usually be correct for this case as well

Uncaught SyntaxError: Unexpected token ILLEGAL

Related errors: Unterminated String Literal, Invalid Line Terminator

A string literal is missing the closing quote.

How to fix this error: Ensure all strings have the correct closing quote.

Uncaught TypeError: Cannot read property ‘foo’ of null, Uncaught TypeError: Cannot read property ‘foo’ of undefined

Related errors: TypeError: someVal is null, Unable to get property ‘foo’ of undefined or null reference

Attempting to read null or undefined as if it was an object. For example:

var someVal = null;
console.log(someVal.foo);

How to fix this error: Usually caused by typos. Check that the variables used near the line number pointed by the error are correctly named.

Uncaught TypeError: Cannot set property ‘foo’ of null, Uncaught TypeError: Cannot set property ‘foo’ of undefined

Related errors: TypeError: someVal is undefined, Unable to set property ‘foo’ of undefined or null reference

Attempting to write null or undefined as if it was an object. For example:

var someVal = null;
someVal.foo = 1;

How to fix this error: This too is usually caused by typos. Check the variable names near the line the error points to.

Uncaught RangeError: Maximum call stack size exceeded

Related errors: Uncaught exception: RangeError: Maximum recursion depth exceeded, too much recursion, Stack overflow

Usually caused by a bug in program logic, causing infinite recursive function calls.

How to fix this error: Check recursive functions for bugs that could cause them to keep recursing forever.

Uncaught URIError: URI malformed

Related errors: URIError: malformed URI sequence

Caused by an invalid decodeURIComponent call.

How to fix this error: Check that the decodeURIComponent call at the error’s line number gets correct input.

XMLHttpRequest cannot load http://some/url/. No ‘Access-Control-Allow-Origin’ header is present on the requested resource

Related errors: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://some/url/

This error is always caused by the usage of XMLHttpRequest.

How to fix this error: Ensure the request URL is correct and it respects the same-origin policy. A good way to find the offending code is to look at the URL in the error message and find it from your code.

InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable

Related errors: InvalidStateError, DOMException code 11

Means the code called a function that you should not call at the current state. Occurs usually with XMLHttpRequest, when attempting to call functions on it before it’s ready.

var xhr = new XMLHttpRequest();
xhr.setRequestHeader('Some-Header', 'val');

In this case, you would get the error because the setRequestHeader function can only be called after calling xhr.open.

How to fix this error: Look at the code on the line pointed by the error and make sure it runs at the correct time, or add any necessary calls before it (such as xhr.open)

Conclusion

JavaScript has some of the most unhelpful errors I’ve seen, with the exception of the notorious Expected T_PAAMAYIM_NEKUDOTAYIM in PHP. With more familiarity the errors start to make more sense. Modern browsers also help, as they no longer give the completely useless errors they used to.

What’s the most confusing error you’ve seen? Share the frustration in the comments!

Want to learn more about these errors and how to prevent them? Detect Problems in JavaScript Automatically with ESLint.

Website performance monitoring

Website performance monitoring

Jani Hartikainen

About Jani Hartikainen

Jani Hartikainen has spent over 10 years building web applications. His clients include companies like Nokia and hot super secret startups. When not programming or playing games, Jani writes about JavaScript and high quality code on his site.

codeutopia.netjhartikainenPosts

To give back to our community of developers, we looked at our database of thousands of projects and found the top 10 errors in JavaScript. We’re going to show you what causes them and how to prevent them from happening. If you avoid these «gotchas,» it’ll make you a better developer.

Because data is king, we collected, analyzed, and ranked the top 10 JavaScript errors. Rollbar collects all the errors for each project and summarizes how many times each one occurred. We do this by grouping errors according to their fingerprints. Basically, we group two errors if the second one is just a repeat of the first. This gives users a nice overview instead of an overwhelming big dump like you’d see in a log file.

We focused on the errors most likely to affect you and your users. To do this, we ranked errors by the number of projects experiencing them across different companies. If we looked only at the total number of times each error occurred, then high-volume customers could overwhelm the data set with errors that are not relevant to most readers.

Here are the top 10 JavaScript errors:

Each error has been shortened for easier readability. Let’s dive deeper into each one to determine what can cause it and how you can avoid creating it.

1. Uncaught TypeError: Cannot read property

If you’re a JavaScript developer, you’ve probably seen this error more than you care to admit. This one occurs in Chrome when you read a property or call a method on an undefined object. You can test this very easily in the Chrome Developer Console.

Screenshot of Uncaught TypeError: Cannot read property

Uncaught TypeError: Cannot read property can occur for many reasons, but a common one is improper initialization of state while rendering the UI components. Let’s look at an example of how this can occur in a real-world app. We’ll pick React, but the same principles of improper initialization also apply to Angular, Vue or any other framework.

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

  render() {
    return (
      <ul>
        {this.state.items.map(item =>
          <li key={item.id}>{item.name}</li>
        )}
      </ul>
    );
  }
}

There are two important things realize here:

  1. A component’s state (e.g. this.state) begins life as undefined.
  2. When you fetch data asynchronously, the component will render at least once before the data is loaded – regardless of whether it’s fetched in the constructor, componentWillMount or componentDidMount. When Quiz first renders, this.state.items is undefined. This, in turn, means ItemList gets items as undefined, and you get an error – «Uncaught TypeError: Cannot read property ‘map’ of undefined» in the console.

This is easy to fix. The simplest way: Initialize state with reasonable default values in the constructor.

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 (
      <ul>
        {this.state.items.map(item =>
          <li key={item.id}>{item.name}</li>
        )}
      </ul>
    );
  }
}

The exact code in your app might be different, but we hope we’ve given you enough of a clue to either fix or avoid this problem in your app. If not, keep reading because we’ll cover more examples for related errors below.

2. TypeError: ‘undefined’ is not an object (evaluating

This is an error that occurs in Safari when you read a property or call a method on an undefined object. You can test this very easily in the Safari Developer Console. This is essentially the same as the above error for Chrome, but Safari uses a different error message.

Screenshot of TypeError: ‘undefined’ is not an object

3. TypeError: null is not an object (evaluating

This is an error that occurs in Safari when you read a property or call a method on a null object. You can test this very easily in the Safari Developer Console.

Screenshot of TypeError: null is not an object

Interestingly, in JavaScript, null and undefined are not the same, which is why we see two different error messages. Undefined is usually a variable that has not been assigned, while null means the value is blank. To verify they are not equal, try using the strict equality operator:

Screenshot of TypeError: null is not an object

One way this error might occur in a real world example is if you try using a DOM element in your JavaScript before the element is loaded. That’s because the DOM API returns null for object references that are blank.

Any JS code that executes and deals with DOM elements should execute after the DOM elements have been created. JS code is interpreted from top to down as laid out in the HTML. So, if there is a tag before the DOM elements, the JS code within script tag will execute as the browser parses the HTML page. You will get this error if the DOM elements have not been created before loading the script.

In this example, we can resolve the issue by adding an event listener that will notify us when the page is ready. Once the addEventListener is fired, the init() method can make use of the DOM elements.

<script>
  function init() {
    var myButton = document.getElementById("myButton");
    var myTextfield = document.getElementById("myTextfield");
    myButton.onclick = function() {
      var userName = myTextfield.value;
    }
  }
  document.addEventListener('readystatechange', function() {
    if (document.readyState === "complete") {
      init();
    }
  });
</script>

<form>
  <input type="text" id="myTextfield" placeholder="Type your name" />
  <input type="button" id="myButton" value="Go" />
</form>

4. (unknown): Script error

The (unknown): Script error occurs when an uncaught JavaScript error crosses domain boundaries in violation of the cross-origin policy. For example, if you host your JavaScript code on a CDN, any uncaught errors (errors that bubble up to the window.onerror handler, instead of being caught in try-catch) will get reported as simply «Script error» instead of containing useful information. This is a browser security measure intended to prevent passing data across domains that otherwise wouldn’t be allowed to communicate.

To get the real error messages, do the following:

1. Send the Access-Control-Allow-Origin header

Setting the Access-Control-Allow-Origin header to signifies that the resource can be accessed properly from any domain. You can replace with your domain if necessary: for example, Access-Control-Allow-Origin: www.example.com. However, handling multiple domains gets tricky, and may not be worth the effort if you’re using a CDN due to caching issues that may arise. See more here.

Here are some examples on how to set this header in various environments:

Apache

In the folders where your JavaScript files will be served from, create an .htaccess file with the following contents:

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

Nginx

Add the add_header directive to the location block that serves your JavaScript files:

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

HAProxy

Add the following to your asset backend where JavaScript files are served from:

rspadd Access-Control-Allow-Origin: *

2. Set crossorigin=»anonymous» on the script tag

In your HTML source, for each of the scripts that you’ve set the Access-Control-Allow-Origin header for, set crossorigin="anonymous" on the SCRIPT tag. Make sure you verify that the header is being sent for the script file before adding the crossorigin property on the script tag. In Firefox, if the crossorigin attribute is present but the Access-Control-Allow-Origin header is not, the script won’t be executed.

5. TypeError: Object doesn’t support property

This is an error that occurs in IE when you call an undefined method. You can test this in the IE Developer Console.

Screenshot of TypeError: Object doesn’t support property

This is equivalent to the error «TypeError: ‘undefined’ is not a function» in Chrome. Yes, different browsers can have different error messages for the same logical error.

This is a common problem for IE in web applications that employ JavaScript namespacing. When this is the case, the problem 99.9% of the time is IE’s inability to bind methods within the current namespace to the this keyword. For example, if you have the JS namespace Rollbar with the method isAwesome. Normally, if you are within the Rollbar namespace you can invoke the isAwesome method with the following syntax:

this.isAwesome();

Chrome, Firefox and Opera will happily accept this syntax. IE, on the other hand, will not. Thus, the safest bet when using JS namespacing is to always prefix with the actual namespace.

Rollbar.isAwesome();

6. TypeError: ‘undefined’ is not a function

This is an error that occurs in Chrome when you call an undefined function. You can test this in the Chrome Developer Console and Mozilla Firefox Developer Console.

Screenshot of undefined is not a function

As JavaScript coding techniques and design patterns have become increasingly sophisticated over the years, there’s been a corresponding increase in the proliferation of self-referencing scopes within callbacks and closures, which are a fairly common source of this/that confusion.

Consider this example code snippet:

function clearBoard(){
  alert("Cleared");
}

document.addEventListener("click", function(){
  this.clearBoard(); // what is “this” ?
});

If you execute the above code and then click on the page, it results in the following error «Uncaught TypeError: this.clearBoard is not a function». The reason is that the anonymous function being executed is in the context of the document, whereas clearBoard is defined on the window.

A traditional, old-browser-compliant solution is to simply save your reference to this in a variable that can then be inherited by the closure. For example:

var self=this;  // save reference to 'this', while it's still this!
document.addEventListener("click", function(){
  self.clearBoard();
});

Alternatively, in the newer browsers, you can use the bind() method to pass the proper reference:

document.addEventListener("click",this.clearBoard.bind(this));

7. Uncaught RangeError

This is an error that occurs in Chrome under a couple of circumstances. One is when you call a recursive function that does not terminate. You can test this in the Chrome Developer Console.

Screenshot of Uncaught RangeError: Maximum call stack

It may also happen if you pass a value to a function that is out of range. Many functions accept only a specific range of numbers for their input values. For example, Number.toExponential(digits) and Number.toFixed(digits) accept digits from 0 to 100, and Number.toPrecision(digits) accepts digits from 1 to 100.

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(105));  //range error!

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

8. TypeError: Cannot read property ‘length’

This is an error that occurs in Chrome because of reading length property for an undefined variable. You can test this in the Chrome Developer Console.

Screenshot of TypeError: Cannot read property ‘length’

You normally find length defined on an array, but you might run into this error if the array is not initialized or if the variable name is hidden in another context. Let’s understand this error with the following example.

var testArray= ["Test"];

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

testFunction();

When you declare a function with parameters, these parameters become local ones. This means that even if you have variables with names testArray, parameters with the same names within a function will still be treated as local.

You have two ways to resolve your issue:

  1. Remove parameters in the function declaration statement (it turns out you want to access those variables that are declared outside of the function, so you don’t need parameters for your function):

    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();
  2. Invoke the function passing it the array that we declared:

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

9. Uncaught TypeError: Cannot set property

When we try to access an undefined variable it always returns undefined and we cannot get or set any property of undefined. In that case, an application will throw “Uncaught TypeError cannot set property of undefined.”

For example, in the Chrome browser:

Screenshot of Uncaught TypeError: Cannot set property

If the test object does not exist, error will throw “Uncaught TypeError cannot set property of undefined.”

10. ReferenceError: event is not defined

This error is thrown when you try to access a variable that is undefined or is outside the current scope. You can test it very easily in Chrome browser.

Screenshot of ReferenceError: event is not defined

If you’re getting this error when using the event handling system, make sure you use the event object passed in as a parameter. Older browsers like IE offer a global variable event, and Chrome automatically attaches the event variable to the handler. Firefox will not automatically add it. Libraries like jQuery attempt to normalize this behavior. Nevertheless, it’s best practice to use the one passed into your event handler function.

document.addEventListener("mousemove", function (event) {
  console.log(event);
})

Conclusion

It turns out a lot of these are null or undefined errors. A good static type checking system like Typescript could help you avoid them if you use the strict compiler option. It can warn you if a type is expected but has not been defined. Even without Typescript, it helps to use guard clauses to check whether objects are undefined before using them.

We hope you learned something new and can avoid errors in the future, or that this guide helped you solve a head scratcher. Nevertheless, even with the best practices, unexpected errors do pop up in production. It’s important to have visibility into errors that affect your users, and to have good tools to solve them quickly.

Rollbar gives you visibility to production JavaScript errors and gives you more context to solve them quickly. For example, it offers additional debugging features like telemetry which tells you what happened on the user’s browser leading up to the error. That’s insight you don’t have outside of your local developer console. Learn more in Rollbar’s full list of features for JavaScript applications.


If you haven’t already, signup for a 14-day free trial of Rollbar and let us help you take control of impactful JavaScript errors. 🙂

Ошибки в JavaScript и как их исправить

original

JavaScript может быть кошмаром при отладке: некоторые ошибки, которые он выдает, могут быть очень трудны для понимания с первого взгляда, и выдаваемые номера строк также не всегда полезны. Разве не было бы полезно иметь список, глядя на который, можно понять смысл ошибок и как исправить их? Вот он!

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

Как читать ошибки?

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

Типичная ошибка из Chrome выглядит так:

Uncaught TypeError: undefined is not a function

Структура ошибки следующая:

  1. Uncaught TypeError: эта часть сообщения обычно не особо полезна. Uncaught значит, что ошибка не была перехвачена в catch, а TypeError — это название ошибки.

  2. undefined is not a function: это та самая часть про ошибку. В случае с сообщениями об ошибках, читать их нужно прямо буквально. Например, в этом случае, она значит то, что код попытался использовать значение undefined как функцию.

Другие webkit-браузеры, такие как Safari, выдают ошибки примерно в таком же формате, как и Chrome. Ошибки из Firefox похожи, но не всегда включают в себя первую часть, и последние версии Internet Explorer также выдают более простые ошибки, но в этом случае проще — не всегда значит лучше.

Теперь к самим ошибкам.

Uncaught TypeError: undefined is not a function

Связанные ошибки: number is not a function, object is not a function, string is not a function, Unhandled Error: ‘foo’ is not a function, Function Expected

Возникает при попытке вызова значения как функции, когда значение функцией не является. Например:

var foo = undefined;
foo();

Эта ошибка обычно возникает, если вы пытаетесь вызвать функцию для объекта, но опечатались в названии.

var x = document.getElementByID('foo');

Несуществующие свойства объекта по-умолчанию имеют значение undefined, что приводит к этой ошибке.

Другие вариации, такие как “number is not a function” возникают при попытке вызвать число, как будто оно является функцией.

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

Uncaught ReferenceError: Invalid left-hand side in assignment

Связанные ошибки: Uncaught exception: ReferenceError: Cannot assign to ‘functionCall()’, Uncaught exception: ReferenceError: Cannot assign to ‘this’

Вызвано попыткой присвоить значение тому, чему невозможно присвоить значение.

Наиболее частый пример этой ошибки — это условие в if:

if(doSomething() = 'somevalue')

В этом примере программист случайно использовал один знак равенства вместо двух. Выражение “left-hand side in assignment” относится к левой части знака равенства, а, как можно видеть в данном примере, левая часть содержит что-то, чему нельзя присвоить значение, что и приводит к ошибке.

Как исправить ошибку: убедитесь, что вы не пытаетесь присвоить значение результату функции или ключевому слову this.

Uncaught TypeError: Converting circular structure to JSON

Связанные ошибки: Uncaught exception: TypeError: JSON.stringify: Not an acyclic Object, TypeError: cyclic object value, Circular reference in value argument not supported

Всегда вызвано циклической ссылкой в объекте, которая потом передается в JSON.stringify.

var a = { };
var b = { a: a };
a.b = b;
JSON.stringify(a);

Так как a и b в примере выше имеют ссылки друг на друга, результирующий объект не может быть приведен к JSON.

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

Unexpected token ;

Связанные ошибки: Expected ), missing ) after argument list

Интерпретатор JavaScript что-то ожидал, но не обнаружил там этого. Обычно вызвано пропущенными фигурными, круглыми или квадратными скобками.

Токен в данной ошибке может быть разным — может быть написано “Unexpected token ]”, “Expected {” или что-то еще.

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

Ошибка с [ ] { } ( ) обычно вызвано несовпадающей парой. Проверьте, все ли ваши скобки имеют закрывающую пару. В этом случае, номер строки обычно указывает на что-то другое, а не на проблемный символ.

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

Unexpected ; обычно вызвано символом ; внутри литерала объекта или массива, или списка аргументов вызова функции. Номер строки обычно также будет верным для данного случая.

Uncaught SyntaxError: Unexpected token ILLEGAL

Связанные ошибки: Unterminated String Literal, Invalid Line Terminator

В строковом литерале пропущена закрывающая кавычка.

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

Uncaught TypeError: Cannot read property ‘foo’ of null, Uncaught TypeError: Cannot read property ‘foo’ of undefined

Связанные ошибки: TypeError: someVal is null, Unable to get property ‘foo’ of undefined or null reference

Попытка прочитать null или undefined так, как будто это объект. Например:

var someVal = null;
console.log(someVal.foo);

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

Uncaught TypeError: Cannot set property ‘foo’ of null, Uncaught TypeError: Cannot set property ‘foo’ of undefined

Связанные ошибки: TypeError: someVal is undefined, Unable to set property ‘foo’ of undefined or null reference

Попытка записать null или undefined так, как будто это объект. Например:

var someVal = null;
someVal.foo = 1;

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

Uncaught RangeError: Maximum call stack size exceeded

Связанные ошибки: Uncaught exception: RangeError: Maximum recursion depth exceeded, too much recursion, Stack overflow

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

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

Uncaught URIError: URI malformed

Связанные ошибки: URIError: malformed URI sequence

Вызвано некорректным вызовом decodeURIComponent.

Как исправить ошибку: убедитесь, что вызовы decodeURIComponent на строке ошибки получают корректные входные данные.

XMLHttpRequest cannot load http://some/url/. No ‘Access-Control-Allow-Origin’ header is present on the requested resource

Связанные ошибки: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://some/url/

Эта проблема всегда связана с использованием XMLHttpRequest.

Как исправить ошибку: убедитесь в корректности запрашиваемого URL и в том, что он удовлетворяет same-origin policy. Хороший способ найти проблемный код — посмотреть на URL в сообщении ошибки и найти его в своём коде.

InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable

Связанные ошибки: InvalidStateError, DOMException code 11

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

var xhr = new XMLHttpRequest();
xhr.setRequestHeader('Some-Header', 'val');

В данном случае вы получите ошибку потому, что функция setRequestHeader может быть вызвана только после вызова xhr.open.

Как исправить ошибку: посмотрите на код в строке, указывающей на ошибку, и убедитесь, что он вызывается в правильный момент или добавляет нужные вызовы до этого (как с xhr.open).

Заключение

JavaScript содержит в себе одни из самых бесполезных ошибок, которые я когда-либо видел, за исключением печально известной Expected T_PAAMAYIM_NEKUDOTAYIM в PHP. Большая ознакомленность с ошибками привносит больше ясности. Современные браузеры тоже помогают, так как больше не выдают абсолютно бесполезные ошибки, как это было раньше.

Какие самые непонятные ошибки вы встречали? Делитесь своими наблюдениями в комментариях.

Google Chrome, JavaScript


Рекомендация: подборка платных и бесплатных курсов JavaScript — https://katalog-kursov.ru/

Джаваскриптовая ошибка «undefined is not a function» довольно загадочна. Как раз поэтому определённым спросом пользуются разъяснительные статьи, из которых читатель, начинающий изучать программирование на JavaScript, способен узнать о том, что такая ошибка (попытка использовать неопределённое значение как функцию) чаще всего возникает при вызове несуществующего метода объекта (а такой вызов, в свою очередь, чаще всего происходит в случае опечатки в названии метода). Такой разъяснительной статьёю может послужить «Ошибки в JavaScript и как их исправить», например.

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

Так и вышло:

Improved exception messages: Goodbye «undefined is not a function». Hello «http://t.co/rMIELG5VoW is not a function» pic.twitter.com/3uykfrTK9O

— Addy Osmani (@addyosmani) 21 февраля 2015

Впрочем, вышеозначенное улучшение сообщения об ошибке произошло только в V8, то есть появится оно только в Google Chrome, в Chromium, в новой Опере, а со временем — в Node.js и в других нодоподобных движках, служащих для запуска внебраузерного джаваскрипта. О внедрении подобного улучшения в остальных браузерах ничего не известно.

Понравилась статья? Поделить с друзьями:
  • Ошибка undefined что это такое
  • Ошибка undefined на сайте что это
  • Ошибка undefined на сайте налоговой
  • Ошибка undefined reference to winmain
  • Ошибка undefined reference to qmain int char