Вы пишете код, всё кажется логичным, но в консоли внезапно всплывает холодное и раздражающее сообщение: «TypeError: ... is not a function». Это не просто баг — это крик вашей программы о том, что вы пытаетесь общаться с ней на разных языках. Понимание этой ошибки — ключ к более глубокому освоению JavaScript и избавлению от часов бесплодного поиска проблемы в неверном месте.
Что скрывается за ошибкой?
По своей сути, TypeError: ... is not a function — это чёткий сигнал от движка JavaScript (V8 в Chrome, SpiderMonkey в Firefox). Он говорит: «В этом месте кода я ожидал увидеть функцию, которую можно вызвать с помощью оператора скобок (), но вместо этого я нашёл что-то другое». Это «что-то другое» может быть: undefined, null, числом, строкой, объектом или даже массивом — но только не функцией.
Важно: В строгом режиме ('use strict') попытка вызвать undefined или null как функцию вызовет именно эту ошибку. В нестрогом режиме это иногда может приводить к более загадочным последствиям.
Типичные сценарии появления ошибки
Давайте разберём самые частые причины, по которым вы можете встретить это сообщение.
1. Опечатка в имени функции или метода
Самая банальная и распространённая причина.
const myObject = {
doSomething: function() { console.log('Done!'); }
};
myObject.doSomethign(); // Опечатка: doSomethign вместо doSomething
// TypeError: myObject.doSomethign is not a function
2. Вызов метода до его инициализации
Часто случается при работе с асинхронным кодом или неправильной последовательности инициализации.
let processor;
setTimeout(() => {
processor = {
start: () => console.log('Processing...')
};
}, 1000);
processor.start(); // Вызов ДО того, как processor получит значение
// TypeError: processor.start is not a function
3. Путаница с контекстом (this)
Классическая проблема JavaScript — потеря контекста вызова.
const buttonHandler = {
message: 'Clicked!',
handleClick: function() {
console.log(this.message);
}
};
const clickCallback = buttonHandler.handleClick;
clickCallback(); // this теперь указывает на глобальный объект (или undefined в strict mode)
// Может выдать TypeError, если на месте this.message ожидалась функция
4. Ошибка в цепочке опциональных вызовов (?.) или доступа к свойствам
Если промежуточное свойство равно null или undefined.
const data = { user: null };
data.user.getName(); // TypeError: Cannot read properties of null
// Безопаснее: data.user?.getName()
Как отлаживать и исправлять?
Не паникуйте. Систематический подход сэкономит вам нервы.
- Прочтите сообщение полностью. В нём указано точное значение, которое не является функцией. Например,
TypeError: myArray[3] is not a functionговорит, что элемент с индексом 3 в массиве — не функция. - Используйте console.log() или debugger. Выведите в консоль переменную, которую пытаетесь вызвать, прямо перед строкой с ошибкой. Увидите её реальный тип и значение.
console.log('Тип processor:', typeof processor); console.log('Значение processor:', processor); processor.start(); - Проверьте цепочку доступов. Если вы вызываете
obj.a.b.c(), убедитесь, что каждое звено (obj.a,obj.a.b) существует и является объектом. - Для методов объектов проверьте контекст (this). При передаче метода как колбэка используйте
.bind()или стрелочные функции.
Совет: Современные IDE и линтеры (ESLint) часто подсвечивают очевидные опечатки в именах свойств и методов. Не пренебрегайте их использованием.
Профилактика лучше, чем лечение
- Используйте TypeScript или JSDoc. Система типов заранее предупредит о многих потенциальных
TypeError. - Опциональная цепочка (?.) и оператор нулевого слияния (??). Эти современные операторы — ваши лучшие друзья для безопасного доступа к свойствам.
- Задавайте значения по умолчанию. При деструктуризации или инициализации переменных.
- Пишите модульные тесты. Они помогут отловить ошибки на ранних этапах.
FAQ: Часто задаваемые вопросы
В чём разница между «is not a function» и «is not defined»?
ReferenceError: ... is not defined означает, что переменной с таким именем вообще не существует в текущей области видимости. TypeError: ... is not a function означает, что переменная существует, но её значение не является функцией.
Почему иногда возникает «is not a function», хотя в коде явно объявлена функция?
Скорее всего, есть проблема с областью видимости или моментом выполнения кода. Функция может быть переопределена позже, или её объявление находится в ветке условия, которое не выполнилось.
Как проверить, является ли переменная функцией, перед вызовом?
Используйте оператор typeof: if (typeof myVar === 'function') { myVar(); }. Либо используйте try...catch для обработки возможной ошибки.
Может ли эта ошибка возникать при вызове встроенных методов, например, map или forEach?
Да, если вы пытаетесь вызвать map не на массиве, а, например, на null, undefined или объекте, у которого нет этого метода. Всегда проверяйте, что переменная является массивом: Array.isArray(myVar).