> Как добавить новый метод в стандартный объект Array через prototype в JavaScript (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Яндекс

Стек: JavaScript

> Пример ответа

Короткий ответ

Добавить метод в Array.prototype можно через присваивание: Array.prototype.myMethod = function() { ... }. Однако на практике это считается плохой практикой, так как может конфликтовать с будущими стандартами, сторонними библиотеками и нарушать инкапсуляцию. Если задача не учебная, лучше использовать отдельные функции или Symbol для уникальности имени. При расширении прототипа важно помнить про enumerability - по умолчанию добавленные свойства видны в for...in.

Подробное объяснение

Array.prototype - это объект, который служит прототипом для всех массивов. Любое свойство или метод, добавленные в него, становятся доступными каждому экземпляру массива через цепочку прототипов.

Механика простая: вы присваиваете функцию свойству Array.prototype. Внутри этой функции this будет ссылаться на конкретный массив, для которого вызван метод. Это позволяет писать методы, которые работают с самим массивом.

Однако есть важные нюансы:

  • Enumerability: по умолчанию свойство, добавленное через присваивание, является enumerable. Это значит, что оно появится в for...in по массиву, что может сломать код, который итерируется по ключам. Чтобы избежать этого, нужно использовать Object.defineProperty с enumerable: false.
  • Конфликты имён: если в будущем стандарт добавит метод с таким же именем, ваш код переопределит его или будет переопределён. Это может привести к трудноуловимым багам.
  • Совместимость: разные библиотеки могут добавлять свои методы в Array.prototype, и они могут конфликтовать между собой.

Альтернативы:

  • Использовать Symbol как имя метода - это гарантирует уникальность.
  • Использовать отдельные функции, принимающие массив аргументом.
  • Создать класс-наследник Array и добавить методы в его прототип.

На практике

На практике расширение Array.prototype допустимо в учебных целях, в полифиллах (когда нужно реализовать метод, который уже есть в стандарте, но отсутствует в старых окружениях) или в очень маленьких проектах с полным контролем над кодом.

В production-коде лучше избегать этого. Если вы пишете библиотеку, никогда не расширяйте прототипы встроенных объектов - это может сломать чужой код. Вместо этого экспортируйте функции или используйте Symbol.

Если вы всё же решите добавить метод, используйте Object.defineProperty с enumerable: false и проверяйте, не существует ли уже метод с таким именем.

Пример кода

JAVASCRIPT
// Плохой способ - enumerable, может конфликтовать
Array.prototype.sum = function() {
return this.reduce((acc, item) => acc + item, 0);
};
// Хороший способ - не enumerable, с проверкой существования
if (!Array.prototype.sum) {
Object.defineProperty(Array.prototype, 'sum', {
value: function() {
return this.reduce((acc, item) => acc + item, 0);
},
enumerable: false,
writable: true,
configurable: true
});
}
// Использование Symbol для уникальности
const sumSymbol = Symbol('sum');
Array.prototype[sumSymbol] = function() {
return this.reduce((acc, item) => acc + item, 0);
};
const arr = [1, 2, 3];
console.log(arr.sum()); // 6
console.log(arr[sumSymbol]()); // 6

Как отвечать на собеседовании

Начните с прямого ответа: показать синтаксис. Затем сразу переходите к нюансам - enumerability, конфликты имён, альтернативы. Это покажет, что вы понимаете не только механику, но и последствия.

Хорошо упомянуть, когда это оправдано: полифиллы, учебные примеры, изолированные проекты. И подчеркнуть, что в библиотеках и крупных проектах это анти-паттерн.

Если интервьюер спрашивает про this внутри метода - объясните, что this будет массивом, на котором вызван метод, и что это работает благодаря механизму вызова методов.

Что проверяет интервьюер

Интервьюер проверяет:

  • Понимание прототипного наследования и цепочки прототипов.
  • Знание того, как работает this в контексте вызова метода.
  • Осознание побочных эффектов модификации встроенных прототипов.
  • Умение предложить альтернативные подходы.
  • Знание Object.defineProperty и Symbol.

Это вопрос-индикатор: кандидат, который просто скажет "надо присвоить функцию в prototype" и остановится, покажет поверхностное понимание. Кандидат, который сразу заговорит о рисках и альтернативах, - senior.

Типичные ошибки

  • Забыть про enumerability - метод появится в for...in, что сломает итерацию по массиву.
  • Не проверять существование метода - можно переопределить уже существующий или добавленный другой библиотекой.
  • Использовать стрелочную функцию - она не имеет своего this, поэтому метод не будет работать.
  • Думать, что this внутри метода - это сам Array.prototype, а не экземпляр массива.
  • Предлагать расширение прототипа как основное решение в production-коде без оговорок.
  • Не упоминать Symbol как способ избежать конфликтов имён.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью