Что такое метод в JavaScript: функции, методы объекта, this и переменные

Что такое метод в JavaScript: функции, методы объекта, this и переменные Полезное

Метод в JavaScript — это функция, которая хранится в свойстве объекта и вызывается через точку: user.greet(), "otus".toUpperCase(), Math.max(3, 7). От обычной функции метод отличается не синтаксисом тела, а способом вызова: при вызове через точку внутри функции доступен this — объект, у которого ее вызвали.

Ниже разберу, как объявлять функции (включая стрелочные), как устроены методы объектов и классов, по какому правилу определяется this и где при этом нужны let и const. Все примеры проверены в Node.js 24 LTS (вывод совпал в Node.js 22 и 26).

Мини-словарь: переменная, функция, свойство, метод

Термин Что это Пример
Переменная Имя, связанное со значением let count = 0
Функция Значение, которое можно вызвать со скобками function sum(a, b) {...}
Свойство Пара «ключ — значение» внутри объекта user.name
Метод Свойство, значение которого — функция user.greet()

Главное: метод — частный случай функции. Любую функцию можно положить в свойство объекта, и она станет методом этого объекта.

Минимальный пример: объект с методом

const user = {
  name: "Анна",
  city: "Казань",
  greet() {
    return `Привет, я ${this.name}, город: ${this.city}`;
  },
};

console.log(user.greet());          // вызов метода
console.log(typeof user.greet);     // метод - это функция
console.log("otus".toUpperCase());  // встроенный метод строки
console.log(Math.max(3, 7, 2));     // метод встроенного объекта Math

В консоли появится:

Привет, я Анна, город: Казань
function
OTUS
7

Разбор по строкам:
— greet() {...} — краткая запись метода (с ES2015), то же самое, что greet: function () {...};
— this.name внутри метода читает свойство того объекта, у которого вызвали greet, — здесь user;
— typeof показывает, что метод — обычное значение типа function;
— у строк, чисел и встроенных объектов (Math, Date, JSON) методы уже есть, их не нужно объявлять.

Переменные: let, const и var

Методы и функции почти всегда работают с переменными, поэтому сначала о том, как их объявлять. В современном коде используют const по умолчанию и let, когда значение нужно переприсвоить. var встречается в старом коде.

const limit = 10;
let count = 0;
count = count + 1;          // let можно переприсвоить
console.log(count);

const settings = { theme: "dark" };
settings.theme = "light";   // менять содержимое объекта можно
console.log(settings.theme);

try {
  limit = 20;               // а переприсвоить const нельзя
} catch (e) {
  console.log(e.name + ": " + e.message);
}

try {
  console.log(total);       // обращение до объявления let
  let total = 5;
} catch (e) {
  console.log(e.name + ": " + e.message);
}

console.log(old);           // var поднимается со значением undefined
var old = 1;

if (true) {
  var a = "var виден снаружи блока";
  let b = "let виден только в блоке";
}
console.log(a);
console.log(typeof b);
1
light
TypeError: Assignment to constant variable.
ReferenceError: Cannot access 'total' before initialization
undefined
var виден снаружи блока
undefined
const let var
Область видимости блок {} блок {} вся функция
Переприсвоить нельзя (TypeError) можно можно
Обращение до объявления ReferenceError ReferenceError undefined без ошибки
Повторное объявление в той же области SyntaxError SyntaxError допускается

Важная граница: const запрещает переприсвоить переменную, но не делает объект неизменяемым. Для этого есть Object.freeze(), и то он замораживает только верхний уровень объекта.

Три способа объявить функцию

// 1. Объявление функции (function declaration)
console.log(sum(2, 3));            // работает до строки объявления

function sum(a, b) {
  return a + b;
}

// 2. Функциональное выражение
const multiply = function (a, b) {
  return a * b;
};

// 3. Стрелочная функция
const square = (x) => x * x;       // короткая форма: return неявный
const describe = (name, age = 18) => {
  return `${name}, ${age}`;        // в фигурных скобках return нужен явно
};

function noReturn() {
  const x = 1;
}

console.log(multiply(4, 5));
console.log(square(9));
console.log(describe("Олег"));
console.log(describe("Олег", 30));
console.log(noReturn());
5
20
81
Олег, 18
Олег, 30
undefined

age = 18 — значение параметра по умолчанию, оно подставляется, если аргумент не передан. Функция без return возвращает undefined.

Свойство Объявление function f(){} Выражение const f = function(){} Стрелочная const f = () => {}
Можно вызвать до строки объявления да нет нет
Собственный this да, зависит от вызова да, зависит от вызова нет, берется снаружи
Собственный arguments да да нет
Вызов через new да да нет (TypeError)
Типичное применение именованные функции модуля функция как значение колбэки, короткие преобразования

Две частые ошибки со стрелочными и выражениями

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

try {
  console.log(twice(4));
} catch (e) {
  console.log(e.name + ": " + e.message);
}
const twice = (x) => x * 2;

const bad = (x) => { x * 2 };
console.log(bad(4));
const makeUser = (name) => ({ name });
console.log(makeUser("Ира"));
ReferenceError: Cannot access 'twice' before initialization
undefined
{ name: 'Ира' }

Исправление: объявлять const-функции выше места вызова; в стрелочной с фигурными скобками писать return явно, а объект в короткой форме оборачивать в круглые скобки ({ name }).

Методы объекта: вызов, ссылка и добавление

const person = {
  firstName: "Иван",
  lastName: "Петров",
  fullName() {
    return this.firstName + " " + this.lastName;
  },
};

console.log(person.fullName());    // со скобками: вызов, результат - строка
console.log(person.fullName);      // без скобок: сама функция
person.initials = function () {    // добавить метод после создания
  return this.firstName[0] + "." + this.lastName[0] + ".";
};
console.log(person.initials());
console.log(Object.keys(person));
Иван Петров
[Function: fullName]
И.П.
[ 'firstName', 'lastName', 'fullName', 'initials' ]

Скобки решают все: person.fullName() — вызов метода, person.fullName — ссылка на функцию (так ее передают как колбэк). Формат строки [Function: fullName] — это вывод console.log в Node.js, браузерная консоль покажет функцию иначе.

Как работает this: правило по способу вызова

this определяется не местом, где функция написана, а тем, как ее вызвали. Исключение — стрелочные функции: у них своего this нет, они берут его из окружающего кода.

Как вызвали Чему равен this
obj.method() obj
f() без объекта, строгий режим undefined
f() без объекта, нестрогий режим глобальный объект (window в браузере)
f.call(x), f.apply(x), f.bind(x)() x
new F() новый создаваемый объект
стрелочная функция this окружающего кода

Модули ES и тела классов всегда работают в строгом режиме; в обычном скрипте его включает строка "use strict".

Ошибка: метод «оторвали» от объекта

"use strict";

const user = {
  name: "Анна",
  greet() {
    return "Я " + this.name;
  },
  greetArrow: () => {
    return "Я " + this?.name;       // у стрелочной нет своего this
  },
};

console.log(user.greet());           // this = user
console.log(user.greetArrow());      // this взят снаружи объекта

const greet = user.greet;            // метод «оторвали» от объекта
try {
  console.log(greet());
} catch (e) {
  console.log(e.name + ": " + e.message);
}

const bound = user.greet.bind(user); // исправление 1: привязать this
console.log(bound());

const wrapped = () => user.greet();  // исправление 2: вызвать через точку
console.log(wrapped());

const other = { name: "Олег" };
console.log(user.greet.call(other)); // this задан явно
Я Анна
Я undefined
TypeError: Cannot read properties of undefined (reading 'name')
Я Анна
Я Анна
Я Олег

Что произошло. greet() без точки получил this = undefined, и чтение .name упало. Та же потеря this происходит, когда метод передают колбэком, но падения может и не быть: в setTimeout(user.greet, 100) this станет объектом Timeout в Node.js или window в браузере, а в button.addEventListener("click", user.greet) — элементом кнопки. Метод молча прочитает чужое name (undefined или пустую строку) вместо "Анна", и такую ошибку заметить труднее, чем TypeError. Исправления — bind или обертка-стрелочная.

Строка Я undefined — следствие стрелочной функции в роли метода: this взят из кода вокруг объекта. В Node.js в формате CommonJS это пустой module.exports, в браузерном скрипте — window, поэтому результат зависит от среды. Вывод: методы объекта объявлять краткой записью greet() {}, а не стрелочной.

Где стрелочная функция как раз нужна

"use strict";

const timer = {
  seconds: 0,
  startBroken() {
    [1, 2, 3].forEach(function () {
      this.seconds += 1;   // обычная функция: свой this, не timer
    });
  },
  start() {
    [1, 2, 3].forEach(() => {
      this.seconds += 1;   // стрелочная берет this из метода start
    });
  },
};

try {
  timer.startBroken();
} catch (e) {
  console.log(e.name + ": " + e.message);
}
timer.start();
console.log(timer.seconds);
TypeError: Cannot read properties of undefined (reading 'seconds')
3

Внутри метода колбэк лучше писать стрелочным: он видит this метода. В нестрогом режиме startBroken не упал бы, а молча записал NaN в глобальный объект — такую ошибку искать дольше.

Методы класса, геттеры и статические методы

В классах методы объявляются той же краткой записью. Добавляются два вида: геттер (читается как свойство) и статический метод (вызывается у самого класса).

class Counter {
  #value = 0;                 // приватное поле

  increment(step = 1) {       // метод экземпляра
    this.#value += step;
    return this;              // возвращаем объект - вызовы можно сцепить
  }

  get value() {               // геттер: читается как свойство, без скобок
    return this.#value;
  }

  static from(n) {            // статический метод: вызывается у класса
    return new Counter().increment(n);
  }
}

const c = new Counter();
c.increment().increment(5);
console.log(c.value);
console.log(Counter.from(10).value);
console.log(typeof c.increment, typeof Counter.from);
console.log(Object.keys(c));
6
10
function function
[]

Object.keys(c) пуст: методы класса хранятся не в самом объекте, а в его прототипе (Counter.prototype), общем для всех экземпляров, а приватное поле #value в список ключей не попадает.

Встроенные методы, которые нужны с первого дня

const s = "  JavaScript  ";
console.log(s.trim().length);
console.log(s.trim().toLowerCase());
console.log("otus.ru".includes("otus"));
console.log("a-b-c".split("-"));
console.log((3.14159).toFixed(2));
console.log(Number.parseInt("42px", 10));
console.log(Math.round(2.5), Math.round(-2.5));
const d = new Date(Date.UTC(2026, 8, 24));
console.log(d.toISOString());
console.log(d.getUTCMonth());
10
javascript
true
[ 'a', 'b', 'c' ]
3.14
42
3 -2
2026-09-24T00:00:00.000Z
8

Две ловушки из этого вывода. Math.round округляет половину в сторону плюс бесконечности, поэтому -2.5 дает -2, а не -3. Месяцы в Date считаются с нуля: сентябрь — это 8. toFixed возвращает строку, а не число.

Методы строк не меняют исходную строку, а возвращают новую: строки в JavaScript неизменяемы. Старые методы вроде bold(), blink(), fontcolor() и document.write() из учебников 2000-х сохранены для совместимости, но в новом коде не используются: разметку меняют через DOM (textContent, classList).

Если не получилось: симптом -> причина

Симптом Частая причина Что сделать
Cannot read properties of undefined (reading '...') внутри метода метод вызван без точки или передан колбэком bind(obj) или () => obj.method()
Метод возвращает undefined нет return или стрелочная с {} добавить return
В консоли текст функции вместо результата забыты скобки вызова obj.method(), а не obj.method
Cannot access 'x' before initialization обращение к let/const до объявления перенести объявление выше
Assignment to constant variable переприсваивание const let, если значение должно меняться
... is not a function опечатка в имени метода или у значения нет такого метода проверить typeof obj.method

Выводы

  • Метод — это функция в свойстве объекта; от функции его отличает вызов через точку и доступ к this.
  • this задается способом вызова: obj.method() дает obj, «оторванный» метод в строгом режиме получает undefined.
  • Методы объекта удобно писать краткой записью method() {}, колбэки внутри методов — стрелочными функциями.
  • Переменные объявляют через const по умолчанию и let для переприсваивания; const не замораживает содержимое объекта.
  • Встроенные методы строк и Math возвращают новые значения и имеют свои граничные случаи (Math.round(-2.5), месяцы Date с нуля).

Где применяется / связь с практикой

Освойте тему на практике

Методы и this встречаются в любом фронтенд-коде: обработчики событий, компоненты, классы сервисов, работа со строками и датами в формах. Ошибки с потерянным this и неявным return — одни из самых частых у начинающих, и они быстро уходят, когда пишешь много небольших задач с проверкой. Системно пройти переменные, функции, объекты и DOM с практикой и ревью можно на курсе «JavaScript-разработчик. Базовый уровень». Разобрать отдельную тему с преподавателем вживую помогут открытые уроки Otus.

FAQ

Чем метод отличается от функции-свойства, которое не использует this?
Технически ничем: это все равно метод объекта. Если this внутри не нужен, такую функцию часто выносят из объекта в обычную функцию модуля.

Можно ли вызвать метод одного объекта для другого?
Да, через call или apply: user.greet.call(other) выполнит метод с this = other. Так же работают заимствованные методы, например Array.prototype.slice.call(arguments) в старом коде.

Почему у числа нельзя написать 5.toFixed(2)?
Парсер читает точку после 5 как десятичную. Нужно (5).toFixed(2) или 5..toFixed(2); у переменной (n.toFixed(2)) проблемы нет.

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)