Почему это Object.defineProperty(), а не this.defineProperty() (для объектов)?

Я работаю над проектом JavaScript, и мне было просто интересно, почему экземпляр объекта не наследует defineProperty() и другие методы, вместо того, чтобы вызывать суперкласс (суперобъект?) Object метод.

Я посмотрел документы MDN, и на самом деле существуют "нестандартные" методы свойств.

Но это не рекомендуется. Почему переход будет к Object методы?

Мне кажется, что-то вроде instance.defineProperty(...) лучше, чем Object.defineProperty(instance, ...), То же самое я бы сказал и о некоторых других методах Object.

3 ответа

Решение

Это чтобы избежать коллизий - в общем, проблемы с объектами, у которых нет свойства со значением, которое вы ожидаете.
Объекты в JS часто используются как карты ключ-значение, а ключи могут быть произвольными строками - например, __defineGetter__, hasOwnProperty или что-то менее особенное. Теперь, когда вы хотите вызвать такую ​​функцию для неизвестного объекта - как hasOwnProperty часто используется в универсальных функциях перечисления, где может быть передан любой JSON - вы никогда не можете быть уверены, получили ли вы перезаписанное свойство (которое может даже не быть функцией) или оригинал, который вам нужен, или объект наследует свойство совсем. Чтобы избежать этой проблемы (или также этой ошибки IE), вам придется использовать Object.prototype.hasOwnProperty.call - это безобразно.

Итак, пространство имен всех этих функций на Object только полезно, это более чистый API, который отделяет методы отражения от интерфейса приложения объекта. Это также помогает оптимизации (упрощает статический анализ) и облегчает ограничение доступа к API отражения в песочницах - по крайней мере, такова была идея проекта.

Вы могли бы быть счастливы иметь defineProperty в прототипе, но вы можете безопасно использовать его только при работе с известными объектами. Если вы все еще хотите это (как вы знаете, когда использовать, а когда нет), вы можете использовать

Object.defineProperty(Object.prototype, "defineProperty", {
    writable: true,
    enumberable: false,
    value: function(prop, descr) {
        return Object.defineProperty(this, prop, descr); 
    }
});

Это сделано так, чтобы избежать столкновений - помните, каждый метод на Object.prototype это метод в каждом отдельном пользовательском объекте тоже.

Представьте себе объект, для которого вы хотите использовать собственный метод defineProperty - это полностью сломало бы вещи, когда Object.defineProperty был на его прототипе вместо.

Интересно. Единственная причина, по которой я придумал, заключается в том, что людям нравится переписывать прототипы, и такой метод "скрытия" может помочь вам избежать некоторых ошибок. Особенно из-за хорошего имени метода, так как это, скорее всего, будет переписано, чем, например, __defineGetter__,

Кажется, что многие функции зависят от этой функции ( ссылка), поэтому имеет смысл сделать ее более глобальной и безопасной в этом контексте.

Другие вопросы по тегам