Ответ 1
У JavaScript нет точного аналога для методов расширения С#. JavaScript и С# - это совершенно разные языки.
Ближайшая похожая вещь - изменить объект-прототип всех строковых объектов: String.prototype
. Как правило, рекомендуется не модифицировать прототипы встроенных объектов в коде библиотеки, предназначенном для объединения с другим кодом, который вы не контролируете. (Делать это в приложении, где вы контролируете, какой другой код включен в приложение, можно.)
Если вы изменяете прототип встроенного, лучше (на сегодняшний день) сделать это свойство не перечисляемым, используя Object.defineProperty
(ES5+, то есть практически любую современную среду JavaScript, и не IE8¹ или ранее). Чтобы соответствовать перечислимости, возможности записи и конфигурирования других строковых методов, он должен выглядеть следующим образом:
Object.defineProperty(String.prototype, "SayHi", {
value: function SayHi() {
return "Hi " + this + "!";
},
writable: true,
configurable: true
});
(по умолчанию для enumerable
установлено false
.)
Если вам нужно было поддерживать устаревшие среды, то для String.prototype
, в частности, вы, вероятно, могли бы избежать создания перечисляемого свойства:
// Don't do this if you can use 'Object.defineProperty'
String.prototype.SayHi = function SayHi() {
return "Hi " + this + "!";
};
Это не очень хорошая идея, но вам это может сойти с рук. Никогда не делайте этого с Array.prototype
или Object.prototype
; создание перечисляемых свойств для них - это плохая вещь ™.
Подробности:
JavaScript - это прототип языка. Это означает, что каждый объект поддерживается прототипом объекта. В JavaScript этот прототип назначается одним из четырех способов:
- С помощью функции конструктора для объекта (например,
new Foo
создает объект сFoo.prototype
в качестве прототипа) - С помощью функции
Object.create
, добавленной в ES5 (2009) - Свойство доступа
__proto__
(ES2015+, только в веб-браузерах существовало в некоторых средах до его стандартизации) илиObject.setPrototypeOf
(ES2015+) - С помощью движка JavaScript при создании объекта для примитива, потому что вы вызываете метод для него (иногда это называется "продвижением")
Итак, в вашем примере, поскольку firstName
является строковым примитивом, он переводится в экземпляр String
всякий раз, когда вы вызываете для него метод, и этот прототип экземпляра String
- String.prototype
. Таким образом, добавление свойства к String.prototype
, которое ссылается на вашу функцию SayHi
, делает эту функцию доступной для всех экземпляров String
(и эффективно для строковых примитивов, потому что они продвигаются).
Пример:
Object.defineProperty(String.prototype, "SayHi", {
value: function SayHi() {
return "Hi " + this + "!";
},
writable: true,
configurable: true
});
console.log("Charlie".SayHi());