senti uma similaridade no comportamento
A similaridade é apenas na forma como vc usa o método, ou seja, chamando objeto.novoMetodo()
, como se o novoMetodo
fosse realmente um método de objeto
. Mas por baixo dos panos, o mecanismo é completamente diferente.
Em C#, vc apenas tem a impressão que o método foi criado na classe em questão. Mas é só um syntax sugar para a chamada do método estático: no seu exemplo, text.log()
é automaticamente convertida para InjectString.log(text)
. Mas a classe string
permanece inalterada, nenhum método foi realmente adicionado nela.
Por outro lado, em JavaScript, vc realmente está alterando a estrutura do objeto. O método passa a fazer parte dele, e inclusive é herdado pelos objetos filhos.
E tem que tomar cuidado ao adicionar coisas no protótipo, principalmente se vc usa for..in
para iterar. Por exemplo, este código:
Array.prototype.novaFuncao = function() {
};
var array = ['a', 'b'];
for (var i in array) {
console.log(`${i} -> ${array[i]}`);
}
A saída é:
0 -> a
1 -> b
novaFuncao -> function() {
// faz algo
}
Isso porque for..in
também traz as propriedades que estão no protótipo do objeto, mas nem sempre pode ser o que vc quer ao iterar por ele. Então tem que tomar alguns cuidados para evitar o prototype pollution.
Não é exclusivo dessas linguagens
Vale lembrar que isso também existe em outras linguagens.
Por exemplo, em Ruby vc pode modificar qualquer classe:
class UmaClasseQualquer
def novoMetodo(x)
end
end
E neste caso, vc está de fato adicionando um novo método na classe.
Inclusive, dá pra mudar até as classes mais básicas do sistema (embora não seja recomendado):
class Integer
def +(other)
42
end
end
puts 10 + 20
puts 2 + 2
puts 10000 + 2000000
Em Python também dá pra fazer algo similar:
class UmaClasseQualquer:
def func(self, param):
print(f'novo método: {param}')
UmaClasseQualquer.novoMetodo = func
x = UmaClasseQualquer()
x.novoMetodo(42)
Mas diferente de Ruby, não dá para fazer com as classes nativas (como int
ou str
).