Почему это 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__
,
Кажется, что многие функции зависят от этой функции ( ссылка), поэтому имеет смысл сделать ее более глобальной и безопасной в этом контексте.