В чем разница между статическими и нестатическими методами в классах JavaScript
Что проверяют
Понимаете ли вы, где физически живут методы класса в JavaScript: на самом конструкторе или на его prototype. Следом обычно спрашивают, чему равен this в статическом методе и наследуются ли статические методы.
Как отвечать
Класс в JS это синтаксис поверх функции-конструктора и прототипов. Отсюда разница:
- обычный метод: записывается в
MyClass.prototype, один на все экземпляры, вызывается какobj.method(), аthisуказывает на экземпляр и видит его поля; - статический метод: свойство самого конструктора, вызывается как
MyClass.method(). Внутриthisэто класс, а не объект, поэтому поля экземпляра ему недоступны, пока экземпляр не передадут аргументом; - наследование: статика наследуется. При
class Admin extends UserвызовAdmin.create()найдётUser.create, аthisвнутри будетAdmin. На этом строится фабрикаstatic create() { return new this(); }, которая возвращает экземпляр нужного подкласса. Родительский статический метод доступен черезsuper.method(); - доступ из экземпляра:
obj.staticMethodбудетundefined, звать нужно черезMyClass.staticMethod()илиthis.constructor.staticMethod().
Примеры из стандартной библиотеки объясняют назначение лучше определений: Array.from, Array.isArray, Promise.all, Object.keys, Number.isNaN. Это утилиты и фабрики, которым не нужно состояние конкретного объекта. Упомяните и соседей: статические поля, приватные static #cache и блок static { } для однократной инициализации класса.
Где спотыкаются
Говорят, что статический метод «из экземпляра вызвать нельзя вообще». Можно, просто не через this, а через имя класса или this.constructor.
Передают статический метод колбэком: list.map(Parser.parse). Если внутри есть this, он станет undefined, потому что тело класса всегда выполняется в строгом режиме. Нужен bind или стрелочная обёртка.
Путают стрелочную функцию в поле класса с методом. handle = () => {} создаётся заново в каждом экземпляре и в prototype не попадает, это не метод прототипа и тем более не статика.