Почему методы объекта ES5 не были добавлены в Object.prototype?

ES5 добавил количество методы на Object, которые, кажется, нарушают семантическую согласованность JavaScript.

Например, до этого расширения JavaScript API всегда вращался вокруг работы на с самим объектом;

var arrayLength = [].length;
var firstPosInString = "foo".indexOf("o");

... где как новые методы объекта;

var obj = { };
Object.defineProperty(obj, {
    value: 'a',
    writable: false
});

... когда следующее было бы гораздо более конформным:

var obj = { };
obj.defineProperty({
    value: 'a',
    writable: false
});

Может ли кто-нибудь охладить мое любопытство относительно того, почему это так? Есть ли фрагменты кода, которые это сломает? Ведутся ли комитетом по стандартам публичные обсуждения того, почему они выбрали такой подход?


person Isaac    schedule 16.03.2012    source источник


Ответы (2)


Все это очень хорошо объясняется в Документ "Proposed ECMAScript 3.1 Static Object Functions: Use Cases and Rationale" (pdf) самого Аллена Вирфс-Брока (редактор спецификации ES5 и член TC39).

Я бы посоветовал прочитать все это. Он довольно короткий, легко усваиваемый и дает хорошее представление о мыслительном процессе, стоящем за этими дополнениями ES5.

Но, чтобы процитировать соответствующий раздел (выделено мной):

Прежде чем был выбран предложенный API, был рассмотрен ряд альтернативных дизайнов API. В ходе рассмотрения альтернатив мы разработали набор неформальных рекомендаций, которые мы применяли при рассмотрении альтернатив. Эти рекомендации таковы:

  • Аккуратно разделите мета-уровень и уровень приложения.
  • Постарайтесь свести к минимуму площадь поверхности API (т. е. количество методов и сложность их аргументов).
  • Сосредоточьтесь на удобстве использования в именовании и дизайне параметров.
  • Попробуйте повторно применить основные элементы конструкции.
  • Если возможно, разрешите программистам или исполнителям статически оптимизировать использование API.

[...]

Вот некоторые из рассмотренных альтернатив, которые привели к выбранному дизайну.

Очевидная первоначальная идея, следуя примеру уже существующего стандартного метода Object.prototype.propertyIsEnumerable, заключалась в том, чтобы добавить дополнительные методы запроса «propertyIs...» в Object.prototype для других атрибутов и параллельный набор методов изменения атрибутов.

[...]

Когда мы рассматривали этот подход, в нем было несколько вещей, которые нам не нравились и которые казались противоречащими приведенным выше рекомендациям по дизайну API:

  • Он объединяет, а не разделяет мета-уровень и уровень приложения. Как и методы в Object.prototype, методы будут частью общедоступного интерфейса каждого объекта приложения в программе. Таким образом, их должен понимать каждый разработчик, а не только дизайнеры библиотек.

[...]

person kangax    schedule 17.03.2012
comment
Интересно... знаете ли вы, как это связано с Object.create? Крокфорд предложил это как Object.create после принятия этих решений или до этого? - person Dagg Nabbit; 17.03.2012
comment
Хороший вопрос. Понятия не имею :) Кажется, Крокфорд переименовал свой Object.beget в Object.create примерно в то же время, когда обсуждались эти API. FWIW, в документе говорится: 'Обратите внимание, что Object.create без необязательного второго аргумента, по сути, является той же операцией, что и широко разрекламированная функция beget. Мы (возможно, неудивительно) согласны с полезностью этой функции, но считаем, что слово «порождать», вероятно, сбивает с толку многих людей, для которых английский язык не является родным». - person kangax; 17.03.2012
comment
Крокфорд принимал непосредственное участие в разработке ES5 и первоначально предложил beget. create стало предпочтительным именем во время последующих обсуждений дизайна. В своей книге он переименовал beget, чтобы отразить дизайнерское решение ES. - person Allen Wirfs-Brock; 17.03.2012
comment
Спасибо за ссылку на такой актуальный ресурс! - person Isaac; 17.03.2012
comment
Спасибо за очень познавательный отрывок! Однако ссылка на полный документ мертва. Кто-нибудь знает, можно ли еще где-нибудь прочитать этот документ? - person Oliver Sieweke; 24.05.2019

JavaScript API всегда вращался вокруг работы с самим объектом;

Это неправильно. Например. У JSON и Math всегда были свои методы. Таких вещей никто не делает:

var x = 0;
x.cos(); // 1.0
({"a":[0,1],"p":{"x":3,"y":4}}).toJSON();

В Интернете есть множество статей о том, почему расширение Object.prototype — это плохо. Да, они касаются клиентского кода, но возможно это плохо для встроенных методов и по некоторым пунктам.

person kirilloid    schedule 16.03.2012
comment
Я понимаю вашу точку зрения по поводу Math... но различия между расширением Object.prototype как клиента и как самого языка совершенно разные; расширения по языку не отображаются в for ( in ), в отличие от клиентских расширений: jsfiddle.net/mDfCe/1 - person Isaac; 16.03.2012
comment
... это связано с тем, что эти свойства (.constructor, .hasOwnProperty и т. д.) изначально определены с перечисляемым атрибутом, для которого установлено значение false. Начиная с ES5, мы также можем создавать собственные свойства, которые не отображаются в циклах for in (со вторым аргументом Object.defineProperty и Object.create). - person Timo Tijhof; 17.12.2012
comment
Также я ошибаюсь насчет того, что никто этого не делает. В прототипе они используют toJSON для массивов, и это ломает JSON.stringify([]) в прототипе 1.6. - person kirilloid; 17.12.2012