Этот вопрос проверяет понимание прототипного наследования и того, откуда берутся базовые методы вроде toString().
Практически все объекты в JavaScript в итоге наследуются от Object.prototype. Это “базовый” объект в прототипной цепочке, где находятся общие методы (toString, hasOwnProperty и т.д.). Сам Object.prototype обычно наследуется от null, то есть это конец цепочки. Примитивы напрямую не объекты, но при обращении к методам часто временно “оборачиваются” в объект-обёртку.
Прототипная цепочка — это механизм, где объект может искать свойства и методы не только в себе, но и в своём прототипе ([[Prototype]]).
Перед перечислением: когда вы пишете obj.toString(), JS ищет toString сначала в obj, потом в его прототипе, потом выше — пока не найдёт или не упрётся в конец цепочки.
Для обычных объектов конечная “база” — Object.prototype
А “последний шаг” после Object.prototype — это null
const obj = { a: 1 };
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype)); // null
У них есть свои прототипы, но цепочка всё равно обычно приходит к Object.prototype.
Массив:
const arr = [];
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true
console.log(Object.getPrototypeOf(Array.prototype) === Object.prototype); // true
Примитивы сами по себе не наследуются как объекты, но методы у них появляются через временную “обёртку”:
"hi".toUpperCase() работает, потому что строка временно превращается в объект String.
Большинство объектов в JS в итоге наследуются от Object.prototype, а конец прототипной цепочки — null. Это объясняет, почему базовые методы доступны почти “везде”.