LINUX.ORG.RU

Безопасный Monkey-Patching

 


0

1

Сейчас в JS считается дурным тоном расширение прототипов, особенно нативных объектов. ИМХО, это связано с одной стороны, тем, что в JS приходит много народу из статических языков, которые просто не понимают профита, с другой — вопросами оптимизации. Где то читал, что Во времена расцвета Prototype.js это наоборот считалось Best Practice. Да и в руби, например, вроде от него нос не воротят. Ну ладно, времена меняются.

Я тут подумал, а почему бы не сделать вот так

show=function(x){console.log(x); return x}
Object.prototype.call=function(f){return f(this.valueOf())}

// Примеры использования
"foo".call(show)
"foo bar baz".split(" ").call(show)
;({one: 1, two: 2}).call(show)
;({one: 1, two: 2}).call(function(o){for(var i in o){show(o[i])}})

//  foo
//  [ 'foo', 'bar', 'baz' ]
//  { one: 1, two: 2 }
//  1
//  2
Так мы получаем почти то же самое, правда с ущербным синтаксисом через жопу вызова, типа колбеков, но избавляемся от претензий статик-клоунов по-поводу неожиданных эффектов, т.к. главный объект расширен единственным методом. А уже на основе этого можно делать любые обертки. call можно сделать enumerable=false, если чо.

ЗЫ Хотел поставить тег monkey patching, а его нет. Во как. Как бы намекает, насколько сильно разработчики линукс любят правильное ООП

Одна библиотека добавит метод call с одной логикой, другая с другой. Что будешь делать в такой ситуации?

В руби такие изменения хотябы можно ограничивать скоупом модуля.

А более лучший вариант - implicit class в scala.

holuiitipun
()
Ответ на: комментарий от holuiitipun

Нет, можно стандартизировать этот call. Или просто договорится, что любая либа имеет право содержать этот call именно в таком виде. Соответственно, любая либа имеет право реализовывать через этот call любую логику, но сам call не трогать. То есть, например, как в примере выше, ф-ция show могла быть добавлена непосречтвенно в Object.prototype, и тогда мы бы вызывали ее «foo».show() А так «foo».call(show), т.е. компромисс. Нативный объект расширен только единожды.

terminator-101
() автор топика
Ответ на: комментарий от terminator-101

Нет, можно стандартизировать этот call.

Нельзя, кто-то захочет передавать дополнительные, кто-то поддержку промисов.

Ну и что-то подобное есть в undrescore с использованием _.chain

holuiitipun
()
Ответ на: комментарий от terminator-101
_.chain([obj])\
 .map(fn)\ // = твоему call
 .invoce('methodName')\ // = .methodName()
 .first().value() // получаем результат
holuiitipun
()

В прошлый раз ты болел своими событиями в браузере, теперь вот это. Тебе делать нечего больше в жизни?

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.