Вы пишете код, всё идёт хорошо, и вдруг консоль выдаёт холодное и непонятное сообщение: «Uncaught TypeError: ... is not a function». Сердце замирает, а в голове проносится: «Но это же функция! Я её только что объявил!». Не паникуйте. Эта ошибка — одна из самых частых и поучительных в JavaScript. Давайте разберёмся, почему она возникает, как её читать и, главное, как предотвратить.
Что на самом деле говорит вам браузер?
Ошибка TypeError: X is not a function возникает, когда интерпретатор JavaScript пытается вызвать что-то как функцию, но это «что-то» ей не является. Ключевое слово здесь — TypeError: ошибка типа. Вы пытаетесь совершить операцию, не соответствующую типу данных. Представьте, что вы пытаетесь «позвонить», используя книгу вместо телефона. Книга — это ценность (value), но она не поддерживает операцию «звонок». Точно так же объект, строка, число, undefined или даже null не поддерживают операцию вызова ().
Важно: Ошибка возникает именно в момент вызова — когда интерпретатор видит скобки () после выражения. До этого момента переменная может хранить что угодно.
Типичные причины и способы их устранения
Давайте рассмотрим самые распространённые сценарии, которые приводят к этой ошибке.
1. Опечатка в имени функции или методе
Самая банальная и частая причина.
const myObject = {
logMessage: function() { console.log('Привет!'); }
};
myObject.logmessage(); // Ошибка! logmessage с маленькой 'm' не существует.
Решение: Внимательно проверяйте имена. Используйте автодополнение IDE.
2. Вызов значения, которое не является функцией
Вы ожидаете функцию, но получаете что-то другое. Часто это происходит при работе с DOM или результатами промисов.
// Пример 1: Ошибка при поиске элемента
let element = document.getElementById('myButton');
element.addEventListener('click', myHandler); // Всё хорошо.
element(); // TypeError! element — это объект DOM-узла, а не функция.
// Пример 2: Путаница с результатами
let someVar = 'Просто строка';
someVar(); // TypeError! Строку нельзя вызвать.
3. Функция не определена в текущей области видимости
Вы пытаетесь вызвать функцию, которая была объявлена внутри другой функции (замыкание) или ещё не была загружена.
// Функция объявлена позже или в другом файле
myFunction(); // Ошибка, если myFunction ещё не определена.
function init() {
let innerFunc = () => console.log('Внутри!');
}
innerFunc(); // Ошибка! innerFunc видна только внутри init().
4. Асинхронные ловушки: работа с промисами и API
Классическая ошибка новичков — попытка вызвать как функцию результат, который ещё не пришёл.
// Неправильно:
let data = fetch('/api/data'); // fetch возвращает Promise, а не данные
data.json(); // TypeError! data — это промис, а не ответ.
// Правильно:
fetch('/api/data')
.then(response => response.json()) // response — это объект Response с методом .json
.then(data => console.log(data));
Совет для отладки: Перед вызовом всегда проверяйте тип значения с помощью console.log(typeof myVariable). Если вы видите "undefined", "string", "number" или "object" (кроме "function") — вы нашли причину.
Профилактика лучше, чем лечение
Как писать код, который реже страдает от этой ошибки?
- Используйте строгий режим: Добавьте
'use strict';в начало файлов. Это предотвратит некоторые неявные ошибки. - Проверяйте типы: Перед вызовом незнакомых значений из внешних API или библиотек используйте проверки:
if (typeof myVar === 'function') { myVar(); }. - Освойте инструменты разработчика: Современные браузеры в стеке вызова ошибки показывают точную строку и файл, где произошёл сбой. Научитесь читать этот trace.
- Следите за порядком загрузки скриптов: Убедитесь, что функции объявлены до их вызова. Используйте события
DOMContentLoadedили модули ES6.
FAQ: Часто задаваемые вопросы
В чём разница между «is not defined» и «is not a function»?
ReferenceError: X is not defined означает, что интерпретатор вообще не знает о переменной X в текущей области видимости. TypeError: X is not a function означает, что переменная X существует, но её значение не является функцией.
Как отладить эту ошибку в большом проекте?
- Найдите в консоли точную строку кода, где произошла ошибка.
- Посмотрите, какая переменная стоит перед скобками
(). - Добавьте
console.log(название_переменной, typeof название_переменной)прямо перед этой строкой. - Проследите, откуда пришло это значение (возможно, из API, другого модуля или оно изменилось в цикле).
Может ли null или undefined вызвать эту ошибку?
Да, абсолютно. Попытка вызвать null() или undefined() приведёт к TypeError, так как эти примитивные значения не являются вызываемыми объектами.
Почему иногда функция есть, но ошибка всё равно возникает?
Возможно, функция была перезаписана на более позднем этапе выполнения кода. Например, переменной с именем функции могло быть присвоено новое, не функциональное значение. Используйте const для объявления функций, чтобы предотвратить случайную перезапись.