Что означает ошибка TypeError: "x" is not a function
easy

Что означает ошибка TypeError: "x" is not a function

Это когда мы вызываем функцию, которой нет

Ситуация: мы пишем на JavaScript конструктор профилей кошек. Для этого сначала создаём базовый объект с предопределёнными свойствами породы, окраса и клички, а затем добавляем новый — с изменёнными свойствами:

// базовый класс со значениями по умолчанию
function Cat() {
  this.breed = "British Shorthair";
  this.color = "чёрный";
  this.name = "Даромир";
  return this;
}

// метод установки имени
Cat.prototype.name = function (name) {
  this.name = name;
  return this;
};

// создаём новый объект и указываем для него новые значения
const myNewCat = new Cat();
myNewCat.breed ("Scottish Straight");
myNewCat.color ("белый");
myNewCat.name("Бернадетт");

// выводим профиль кота
console.log(myNewCat);

Но при запуске этого кода получаем ошибку:

❌ TypeError: myNewCat.breed is not a function

Странно, почему так, мы ведь просто меняем значения по умолчанию на свои?

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

Когда встречается: ошибка "x" is not a function может возникать в разных ситуациях. Например, программист забыл объявить функцию, но пытается её использовать; разработчик написал метод в локальной зоне видимости скрипта и пытается использовать её в глобальной; или же просто по невнимательности допустил опечатку в вызове функции — такое тоже часто случается.

Что делать с ошибкой "x" is not a function

Смотрите, что у нас было в примере: мы объявили свойства в классе, которые по своей сути — обычные строки:

this.breed = "British Shorthair";
this.color = "чёрный";

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

myNewCat.breed ("Scottish Straight");
myNewCat.color ("белый");

Не надо так.

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

Было в классе:

this.name = "Даромир";

Стало в классе: 

this.catname = "Даромир";

Было в методе:

Cat.prototype.name = function (name) {
this.name = name;
return this;
};

Стало в методе:

Cat.prototype.name = function (name) {
this.catname = name;
return this;
};

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

function Cat() {
  this.breed = "British Shorthair";
  this.color = "чёрный";
  this.catname = "Даромир";
  return this;
}
// метод установки имени
Cat.prototype.name = function (name) {
  this.catname = name;
  return this;
};
// создаём новый объект и указываем для него новые значения
const myNewCat = new Cat();
myNewCat.breed = "Scottish Straight";
myNewCat.color = "белый";
myNewCat.name("Бернадетт");
// выводим профиль кота
console.log(myNewCat);
Что делать с ошибкой "x" is not a function

Теперь разберём другие возможные причины ошибки "x" is not a function

Опечатка в вызове функции

Часто причиной ошибки "x" is not a function оказывается обычная опечатка в названии метода. Нужно проверить правильность написания кода:

// такое написание вызовет ошибку
const x = document.getCatByID("foo");

// правильное написание
const x = document.getCatById("foo");

Отсутствует библиотека сценариев

Это тоже очень простая и частая ошибка, и для её исправления достаточно подключить библиотеку. Например, так импортируется jQuery:

Свойство вызывается как функция

Бывает так, что в объекте ожидалось, что что-то будет методом, а не просто строкой, но его сделали свойством. Тогда попытка вызова свойства как функции приведёт к ошибке:

let cat = {
  name: "Даромир",
  age: 2
};

cat.name();

Вместо того чтобы делать name строковым значением, нужно сделать его функцией, тогда ошибка перестанет возникать:

let cat = {
  name: function() {
    return "Даромир";
  },
  age: 2
};

Объект не содержит функцию

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

let cat = {
  brand: "British Shorthair",
  gender: "male"
};

cat.play();

Чтобы исправить ошибку, нужно проверить, что вызывается существующая функция, или добавить такую функцию в объект:

let cat = {
  brand: "British Shorthair",
  gender: "male",
  play: function() {
    console.log("Коть играет!");
  }
};

cat.play(); 

Функция вызвана не для того объекта

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

const obj = { a: 4, b: 8, c: 15, d: 16, e: 23, f: 42 };

obj.map(function (num) {
  return num * 2;
});

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

const numbers = [4, 8, 15, 16, 23, 43];

numbers.map(function (num) {
  return num * 2;
});

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

Как проверить тип функции

Проверить тип данных можно с помощью оператора typeof:

if (typeof myObject.myMethod === 'function') {
  myObject.myMethod();
} else {
  console.error('myMethod — не функция');
}

Обложка:

Алексей Сухов

Корректор:

Ирина Михеева

Вёрстка:

Маша Климентьева

Соцсети:

Юлия Зубарева

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Еще по теме
easy