Pull to refresh

Comments 44

Наверное дискуссия началась с моего коментария, но по сути не было там дискусии, просто набежало народу, который js в общем -то не знает да и основных принципов программирования тоже. (Хотя минусов наставили, ну да ладно)
Все уже давно решено, все уже давно определились со стратегией и любой адекватный программист скажет:
1) если вы расширяете прототип стандартного объекта, методом из спецификации котоый не поддерживается в старыж версиях браузера, ваш метод должен также работать по спецификации. Алгоритм здесь простой
а) Проверить есть ли метод в прототипе, если есть ничег оне делать
б) если нет — добавить свой, который работает аналогично спецификации
2) если вы расширяете прототип стандартного метода методом не из спецификации, то надо понимать что это путь анархии и если каждая библиотека будет такое делать, вы получите кучу конфликтов, которые порой можно отлавливать днями.

Не зря все современные библиотеки используют замыкания чтобы скрыть все свои внутренности а также имеют no conflict решения, чтобы можно было их переименовать.

О чем тут спорить я честно говоря не знаю, если вы заменяете стандартный метод нативного объекта нестандартным, вы осознанно стреляете себе в ногу и отмазки ну я же писал документация тут не работают! Представьте себе челока который знает спецификацию js, много лет работает js программистом и приходит к вам в проект, даже если он 10 раз прочтет ваши доки его руки будут использовать ваш нестандартный метод по стандарту js, просто из-за привычке, вы просто замедлите его работу. Ну а также он каждый раз будет лазить в доку перед тем как написать строчку кода, боясь что сейчас использует что-то не так.

А также я не вижу ни одного аргумента почему это вам нужно? Если вам нужен метод, выполяющий специальную функцию — добавьте его в свою библиотеку или утилитный «класс» MyClass.myMethod его будет в 100 раз проще найти, читающий код будет всегда знать что и как, понимать что происходит в коде

Ну и по поводу руби, я бы также хотел возразить на счет такого подхода, имхо широкое применения таких приемов приводит к нечитаемсоти кода, да библиотека допустим изолирована от внешнего мира, но вот я использую вашу библиотеку, она опенсоурс и тут нахожу багу, решаю вам помочь и исправить её, идут в библиотеку, читаю ваш код, из-за подмены стандартных методов, читать его будет в 100 раз сложнее, за ошибки я могу принимать правильный код (ведь я думаю что метод работает по другому) и в итоге написать 100 остылей я только все сломаю, буду плеваться и тд. Зачем же так с людьми? Мне кажется такой подход нужен в крайних случаях, например:

вышла новая версия руби и там пофиксили многолетний баг — метод (простите не знаю руби. беру из головы) .map() у массива который проходится по всему массиву не учитывал последний элемент, вы это знали и в свой библиотеке исскусственно решали проблему. И тут все поправили, теперь метод все делает правильно. Но у вас нет времени сейчас на рефакторинг тонны кода для библиотеки, вы решаете быстренько поправить метод, вернув старый баг, дабы библиотека работала во всех версиях руби

Вот для таких временных решений имхо механизм идеален, но никак не в роли основного механизма организации кода.
В Ruby нормой является использование Semantic Versioning: semver.org/ (англ.).

Это соглашение позволяет вам спокойно вносить в проект изменения, ломающие совместимость. Все, о чем вам нужно при этом побеспокоиться, это увеличить первую цифру в номере версии. И тогда все пользователи будут знать: при обновлении до этой версии что-то может поломаться, и будут осторожны.

Далее. В Ruby повсеместно используются два замечательных средства: RVM и Bundler. Благодаря им вы можете в соседних папочках иметь два проекта, которые будут параллельно работать на разных версиях Ruby — каждый на той, с которой совместим.

А при перечислении зависимостей проекта вы можете указывать номера версий в такой нотации: "~> 1.4.12". Этим вы говорите пакетному менеджеру: «используй любую версию этого пакета, но не меньше 1.4.12 и не больше 1.4.9999. Если под рукой подходящей версии нет, скачай самую свежую в этом диапазоне». И благодаря SemVer, вы можете быть уверены, что при установке/обновлении этого пакета в нем не будет нарушений совместимости.

Так что благодаря этим возможностям проблемы, которые вы описали, в мире Ruby не возникают.
Помоему вы сейчас о другом, разные версии руби — ок, не о том речь. Но если я вас правильно понял вы в статье сказали что можете переопредилть стандартный метод нативного объекта только для своего класса\библиотеки.
То есть был метод String.length() который возвращал кол-во символов, вы переопределил его как String.length — который возврвщает кол-во символов минус 1. В итоге я писал что человек который будет читать ваш код подобную тонкость легко выпустит из головы и от сюда у него возникнут разночтения и проблемы восприятия.

Поправьте если я не так говорю.
> То есть был метод String.length() который возвращал кол-во символов, вы переопределил его как String.length — который возврвщает кол-во символов минус 1.

Нет, никто так не делает и никогда не делал. Ни в Ruby, ни в JS.
Вы сами об этом писали.
Предположим, разработчик Вася, который пишет библиотеку Vasya, не стесняется делать манки-патчи: из своей библиотеки он (пере)определяет методы стандартных объектов при помощи конструкции refine.


«Он переопределяет методы стандартных объектов» — ваши слова. Ясное дело что извращаться конкретно над length нието так не будет, но есть же много других методов, которые полне могут вот так заменить, по вашей же логике, заметьте.
А фразу о том, что Sugar неукоснительно следует спецификации ES6, вы проигнорировали? Да и в комментариях я писал лично вам:

> Так что если вы (...) продолжите использоваать (переопределенные) методы по-старинке… внезапно, все будет работать, как вы ожидаете! Ничего не сломается и не нарушится. Вы вообще не заметите факта использования Sugar и будете благополучно писать, как вам подсказывает ваш многолетний опыт.

Вы статью-то читали? :)

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

Прямым текстом же сказано, что библиотека, расширяющая нативные объекты, в проекте должна быть одна и что это вопрос осведомленности.

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

Не знаю, как можно, по вашим словам, 10 раз прочитать фразу «в проекте используется SugarJS, расширяющий нативные методы», и не понять этого. А потом каждый день перечитвать. Наверно, ему нужно распечатать эту фразу и повесить на стеночку. :)

> О чем тут спорить я честно говоря не знаю, если вы заменяете стандартный метод нативного объекта нестандартным, вы осознанно стреляете себе в ногу и отмазки ну я же писал документация тут не работают!

Вы, похоже, не поняли главного. SugarJS так не делает. Дело в том, что переопределенные Sugar'ом методы продолжают работать в неукоснительном соответствии со спецификацией.

Так что если вы, прочитав 10 раз, что в проекте используется SugarJS, этого так и не поймете и продолжите использоавать методы по-старинке… внезапно, все будет работать, как вы ожидаете! Ничего не сломается и не нарушится. Вы вообще не заметите факта использования Sugar и будете благополучно писать, как вам подсказывает ваш многолетний опыт.

> А также я не вижу ни одного аргумента почему это вам нужно?

Да, вы правы, стоило об этом написать. Наверное, это более очевидно для тех, кто начинал серьезно программировать с Ruby. Как говорят, к хорошему быстро привыкаешь: богатая и очень функциональная стандартная библиотека, естественный для динамического языка способ вызова методов, возомжность выстраивать методы в цепочки.

Когда видишь такой код (абстрактный пример):

var result = Math.floor( MyArray.last( arr ) );
if (debug) console.log( «result: », result );
return result;

… вместо такого:

return arr.last().floor().debug();

… то становится как-то, знаете, тоскливо.
Я сейчас общался с вами в стиле «Расширение нативных объектов JavaScript — зло ли это? » А не конкретно о SugarJS. Потому как подобных библиотек много и обсуждать каждую в отдельности не вижу смысла, так что предлагаю окончательно обстрагировать от конкретной либы и обсуждать проблему как таковую.

Вы подняли тему расширения нативных объектов в JS и почемуто всю статью посвятили SugarJS и считаете, что это истина в последней инстанции и только это мы обсуждаем. Если это так, я требую переименовать статью в «Рассуждения о SugarJS „ вопрос будет снят.

Я же рассуждал о первоочередной проблеме, который вы поставили на первое место в статье “Расширение нативных объектов JavaScript — зло ли это? „, это было ваше решение — не мое.
Отсюда — не вижу плохого в использовании библиотеки типо SugarJS в проекте. Я вижу проблему когда вы сами начинате копать прототипы нативных объектов, это чревато вашими же ошибками ну и конечно тем, что вы врятли будите следить за обновлениями спецификации.
также я против того чтобы библиотека типо JQuery, backbone, angular изменяла прототипы нативных объектов ибо вот это будет проблемой если КАЖДАЯ библиотка добавит свое. Если библиотека чисто заточена на синтаксический сахар — то велком.

Теперь по поводу тоскливо, конечно приятно писать в стиле паттерна pipeline и JQ нас прикчил к этому в js, но все-таки сам js имеет некую историю и тут применили некий другой подход.
Поэтому такого arr.last().floor().debug(); в js босюь мы не увидим, ну или по крайне мере это большая переработка, ведь если уж делать то надо поддержать все нативные методы и возможности. Может какие наработки в этом стиле уже есть. надо погуглить на гитхабе.
> Вы подняли тему расширения нативных объектов в JS и почемуто всю статью посвятили SugarJS и считаете, что это истина в последней инстанции и только это мы обсуждаем.

Перечитайте, пожалуйста, вступление к материалу. Это не моя статья, а перевод манифеста SugarJS по вопросу расширения нативных методов. Об этом сказано и в заголовке материала, и во вступлении. Я с уважением отнесся к автору манифеста и не стал перекраивать его публикацию.

Еще одна причина, почему я не стал разводить общие рассуждения, в том, что SugarJS использует целостный и безопасный подход. То, что вы можете испортить себе жизнь необдуманными действиями, никто не оспаривает.

Проведу аналогию. Кухонным ножом вы можете отрезать себе палец. Но это не повод избавляться от всех ножей в квартире, даже если у вас ребенок. Вместо этого вы держите все ножи в одном месте и объясняете ребенку, что в эту полку лазить нельзя. Я не думаю, что статья о том, как опасно раскладывать ножи по всей квартире, будет кому-то интересна.

> Поэтому такого arr.last().floor().debug(); в js босюь мы не увидим

А вы попробуйте разок. Как-нибудь на досуге, на каком-нибудь маленьком проекте. О каких переработках и наработках вы говорите, я не понял.
А вы попробуйте разок. Как-нибудь на досуге, на каком-нибудь маленьком проекте. О каких переработках и наработках вы говорите, я не понял.

Я бы с радостью но эта фитча недоделана и половинчата, поэтомуи начинать не хочется, sugar добавил методы но и пропустил, типо atan2
Или например у sugar Array.prototype.map работает не по стандарту, о чем я и сожалею ['one','two','three'].map('length') ибо по стандарту фргумент map должен быть функцией, согласитесь что уловить этот момент нереально, даже если сказат ьчеловеку что используется sugarjs, ему придется каждый нативный метод сверять с апи библиотеки, это имхо ограничивает свободу.

Я сам лично юзаю polyfill для ES5 в старых браузерах — и да это чудесно, радуюсь и люблю их. Вот еще идея есть юзать препроцессор для arrow function.
Я люблю нувые удобные плюшки, мне нравиться идея с pipeline «return arr.last().floor().debug();» обеими руками за, а еще я прям тащусь от реализации из кофескрипт «if (obj?.obj1?().obj3) { code… }» и хотел бы такое в js.
Но меня угнетают подобные искривления типо как с .map это и есть корень зла — изменение поведения стандартной функции.
Вы по-прежнему не врубаетесь. если вы подключили Sugar, то вы можете использовать:

['one','two','three'].map('length') // => [3, 3, 5]

Но возможность работать по старинке у вас никто не отнимает!

['one','two','three'].map( function(item) { item.length; } ); // По-прежнему работает в соответствии со спецификацией.

В CoffeeScript, кстати, прелести Sugar раскрываются в полной мере.
Вы понимаете что по спецификации ES в случае если параметр мутода .map() получает не функцию мы должны кинуть TypeError.
Давайте тогда говорить что Sugar добавляет часть функций нативные объекты, некоторые из функций могут повторять стандарт ES.

Не надо громких заявлений
Sugar неукоснительно следует спецификации ES6

Почувствуйте разницу. Неукоснительное следование ES6 значит что в браузере который поддерживает ES6 стандарт я могу отключить sugar и получить рабочий код.
Такое ощущение, что ваша цель — оставить за собой последнее слово, даже когда свою неправоту вы уже поняли.

Я вам говорю, что вы не правы в том, будто подключение Sugar требует рефакторинга кода проекта из-за изменившегося синтаксиса методов. А вы в ответ придираетесь к слову «неукоснительно».

Совершенно очевидно, что в той части, где Sugar добавляет новый функционал, будут отличия со спецификацией. Иначе ничего добавить было бы просто невозможно.

Под неукоснительным следованием спецификации, разумеется, идет речь о том, что новый функционал Sugar не изменит стандартного синтаксиса работы с нативными объектами. Все ваши [].map( function() {} ); как работали, так и будут работать.

Вся документация по использованию методов ES6 остается справедливой. К примеру, если вы посмотрите документацию по использованию Array.prototype.map в Mozilla Developer Network developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map, TypeError там вообще не упоминается (TypeError только встречается в коде предлагаемого полифилла). Sugar не противоречит этой документации, не меняет в ней ничего, а только дополняет.

Есть нативные методы, спецификация которых не позволяет Sugar добавить весь желаемый функционал. В таких случаях Sugar в эти методы добавляет только то, что не противоречит спецификации, а желаемую реализацию выносит в новый метод. Например, Array.prototype.forEach( fn, scope ) (полифилл) и Array.prototype.each( fn, index = 0, loop = false ) (свой вариант).

Да и как факт того, что map больше не вызывает TypeError при передаче не-функций в качестве первого аргумента, может нарушить работу вашего проекта? Можно предположить, что после подключения SugarJS придется переписать некоторые юнит-тесты. Но покажите мне программиста, который покрывает тестами не функционал проекта, а функционал нативных методов среды.
А давайте мы сейчас будем серьезными, прекратим демагогию, запишем себе навсегда что developer.mozilla.org — это не спецификация ES, пойдем и скачаем спецификацию найдем описание стандартного метода Array.prototype.map и увидим там четкое руководство кидать TypeError если в параметре не функция.
И на этом вопрос не соответствия спецификации будет закрыт!

Я не юзал Sugar, но в начале дискуссия я был не против юзания либы, однако сейчас я склоняюсь категорично к ответу нет! И в частности если человек хотел бы подключить библиотеку только для того чтобы писать по стандарту ES6 у него не получится ибо неизвестно сколько еще подводных камней мы тут встретим.

И в третьих в реальных проектах подобное фактически не применимо, вы можете представить себе LeafLet или Jquery которые тянут за собой подобный Sugar и ломают проект, а можете себе представить backbone который вместо андрескора сломает проект благодаря использованию sugar?

Область применения Sugar имхо только домашние проекты которые не поползут в паблик, ибо понадобиться вам выкинуть js api на ружу а у вас там везде подобное sugar юзается, да и то вас эта либа приучит писать криво. Потом будите месяцами отучаться от нестандартных костылей.

Слишком много сахара — не есть хорошо, ищите золотую середину.
> пойдем и скачаем спецификацию найдем описания стандартного метода Array.prototype.map и увидем там четкое руководство кидать TypeError если в параметре не функция.

На этот счет я уже ответил в предыдущем комменте. Не вижу никакого смысла повторяться.

> И в частности если человек хотел бы подключить библиотеку только для того чтобы писать по стандарту ES6

SugarJS не является полифиллом ES6 и никогда не стремился. В нем есть полифиллы некоторых фич ES5. Если вам нужен полный функционал ES6 в нынешних браузерах, рекомендую препроцессор Traceur либо предназначенные для этого полифиллы.

> вы можете представить себе LeafLet или Jquery которые тянут за собой подобный Sugar и ломают проект

Нет, ведь в манифесте SugarJS прямо сказано: не используйте SugarJS в библиотеках. И я сам высказывался уже против использования любых необязательных зависимостей в билбиотеках.

> Область применения Sugar имхто только домашние проекты которые не поползут в паблик, ибо понадобиться вам выкинуть js api на ружу а у вас там везде подобное sugar юзается, да и то вас эта либа приучит писать криво. потом будите месяцами отучатья от нестандартных костылей.

Нет, область применения Sugar — проекты практически любой сложности в продакшене, за исключением middleware (библиотек, плагинов...). Я уже раз пять это говорил и уверен, что вы об этом помните, но зачем-то продолжаете приплетать.
Ну в общем вы поняли что в вопросах о спецификации вы были не правы.
Вы никогда не знаете когда ваш код понадобится подключать из вне. Вот мы разрабатываем сервис по бронированию гостиниц, жд и авиа билетов, недавно нам поступило требования реализовать возможность подключения виджетов этого сервиса во внешние сайты, без Iframe, основной код ведь у нас берется с самого сервиса, работа с даннами и тд никуда не делаись, мы просто дописали новое вью для отрисовки нового вида и юзаем идиный код на сайте и в подключаемых виджетах. А было бы что-то типо sugarjs? был бы повод переписать (

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

как я сказал я не против добавление каки-то плюшек, но сделайте map() и propertyMap() к примеру. Я не знаю какие еще подводные камни можно встретить, предполагаю что многие.
Больше всего мне не нравиться что Sugarjs недоделан с любой стороны и ES6 полностью не имлементит, и методы стандартные портит и все стандартные методы не юзает, те же методы Math не все перехали в Number.

Хорошая библиотека для сайта хомячка. но не для серьезного проекта, который мейнтейнить многие годы!
Я думаю что все кто работал с javascript в Magento согласиться что не допустимо расширение нативных объектов JS. Когда увидиш какие костили необходимо городить чтобы заставить defer работать во всех броузерах — начинаеш ненавидить авторов библиотек. И это заметьте конфликт досктаточно качественно написаных и в свое время популярных библиотек PrototypeJs и ExtJS.

Так что если ваш проект загнеться через год, то можете в нем использовать все что хотите, а если нет то вы в любом случаи избавитесь от спорных практик, неважно сразу или через н лет по необходимости…
> И это заметьте конфликт досктаточно качественно написаных и в свое время популярных библиотек PrototypeJs и ExtJS.

Если вы прочитали хотя бы первый абзац авторского текста статьи, то первое, что вы должны были заметить, эт о сравнение SugarJS с PrototypeJS: Sugar работает иначе и не наступает на грабли, разбившие лоб Prototype.
Можете пояснить, в чем будет/уже есть проблема вот скажем такого кода:

Array.prototype.randomElement = function() {
	return this[Math.floor(Math.random()*(this.length))];
};
Array.prototype.last = function() {
	return this[this.length - 1];
}
String.prototype.last = function() {
	return this[this.length - 1];
}


Исходя из прочитанного, получается что даже такие маленькие хелперы очень желательно оформлять не расширением прототипов.
А моя библиотека делает это так:

Array.prototype.randomElement = function() {
        this.last = this[Math.floor(Math.random()*(this.length))];
	return this.last;
};
Array.prototype.last = function() {
	return this.last;
}
String.prototype.last = function() {
 	return this.split(" ").pop();
}


Имеет право на жизнь? Да! Ничуть не меньше вашего! А теперь подключите обе библиотеки и удачного дебагинга проекта.
А интересно, префиксы в названиях разве не спасут от проблем с конфликтами?
Хотя конечно это из области «костыль лучше».
А если давать имена из 1000 символов, то все будет ваапще хорошо. А написав в любимой IDE «my name is». я получу подвисание в ожидании 100500 методов в автокомплите? И буду их разгребать? и опятьже почему обе библиотеки не могут иметь одинаковых префиксов? Как я понимаю префикс — 2-4 символа, вполне ожидаемо что 2 мои любимые библиотеки будут иметь одиаковый префикс.
Почему бы просто не оставить код ВАШЕЙ библиотеки внутри вашей библиотеки.
А главное объясните мне в чем будет выйгрыш? Где профит такого решения?
Про префиксы, я и не защищаю это способ, мне просто интересно разобраться в сути проблемы и её вариантов решения (и плохих и хороших).
вообще-то нет, Ваш код не очень хорош в плане расширения методов класса. Предпочтительнее использовать

Object.defineProperty(Array.prototype, {configurable: true, enumerable: false, writable: false, value: function(...) {… } });

чтобы Ваши расширения нативных объектов не были публично перечисляемы
Это наверное надо было бы на комент выше ответить, ибо не я этот код писал. Ну и привет IE8?
Ну и обсуждалась не проблема enumerable а проблема самого факта добавления
Промазал. Ну IE8 сейчас в принципе можно не рассматривать — его доля ничтожно мала, как и доля IE6 и IE7.
Ну при расширении прототипов Array при перечислении for..in рискуем получить что-то такое:
var arr = [1,2,3];
for(var key in arr){
console.log(key);
}

=> 1, 2, 3, 'randomElement', 'last'

Т.е. если разработчик зачем-то использует for..in для массива, да ещё и не озаботился hasOwnProperty добавить, то он получает проблемы.
Массивы нельзя обходить с помощью "for-in".
"for-in" — это оператор получения свойства Объекта.
Я о чём и говорю.

> если разработчик зачем-то использует for..in для массива
— акцент на слове «зачем-то»).

Ну некоторые и массивы с true/false сравнивают. А потом кричат, какой js плохой.
Вообще перебирать так массив и глупо и долго =) (перфоманс ужасный)
Ну SugarJS так и делает: github.com/andrewplummer/Sugar/blob/master/lib/array.js#L736

Я считаю, что проблем с этим кодом нет и, при соблюдении рекомендаций статьи (в частности, билблиотека, переопределяющая нативные методы, не будет.

За исключением одной: противники расширения нативных объектов закидают шапками. :)
тут, как бы, есть один нюанс — минусы вы сами перечислили. А вот плюсов в расширении нэтивных объектов никаких :)
Добавил немного в конец статьи.
Ты(вы) добавил в конец статьи про чейнинг. всеравно остается проблема что нэтивные методы чейнинг всеравно не поддерживают, и если их не заменять то получается что тут чейнить можно, а тут — нет, и это странно. ( а если заменять то это разрыв шаблона и лишние баги попути :)

Ну и кажется это довольно ортогонально расширению стандартных объектов:
_.chain(data)
             .find({ types: { main: 'context' } })
             .result('context')
             .where('full_url')
             .value()
> Обходить массив при помощи цикла for..in тоже возможно, но это не считается хорошей практикой. Если вы решили использовать этот подход, всегда применяйте метод hasOwnProperty, чтобы проверять, принадлежат ли свойства непосредственно объекту (см. последний пример в раскрывашке выше).

Кроме прочего, кстати, у массива могут быть свои свойства. Ну вот примерно так:
var arr = [1,2,3];
arr.foo = 20;

И это свойство также будет включено при for..in, причём hasOwnProperty от него не спасёт. Так что нужно за этим внимательно следить, и, если такие свойства не нужны, вообще не использовать for..in для массивов.

А вообще очень интересен этот давний спор про прототипы… Почему никто не делает так вот?)
String.isCyrrilic; // function()…
String.prototype.isCyrillic; // undefined
Sugar.usePrototypes();
String.prototype.isCyrillic; // function()…

То есть, мы подключаем библиотеку, и сами выбираем, использовать ли прототипы.

А ещё есть RightJS, у которого, если мне память не изменяет, 2 разных версии — с прототипами и без.

P.S. извиняюсь за отсутствие тега source ).
Началось… Вы хоть проверяйте прежде чем писать…

String.isCyrrilic = function(){return true}
"test".isCyrrilic()
TypeError: Object test has no method 'isCyrrilic'

ой…

То что вы метод добавили не в прототип, а прямо в класс проблему нашу не решило, вы загадили методами сам объект String (давате называть его класс, хотя правильно было бы функция конструктор). Ваш метод isCyrrilic теперь недоступен для объектов порождаемых конструктором, так как поиск будет происходить по prototype chain и scope, и теперь вам придется обращаться к нему так

String.isCyrrilic(obj) 

Только это не решает проблемы наличия такого еж метода у меня в библиотеке

String.isCyrrilic = function(){return false}

Эмм… я совсем другое имел в виду.

> TypeError: Object test has no method 'isCyrrilic'
Естественно, поскольку вы добавили метод в класс, а не в его прототип. А свойства к экземплярам класса переходят именно из прототипа.

Итак, сначала. Я предложил, чтобы библиотека касалась прототипов (да и вообще встроенных объектов, если уж на то пошло) лишь по запросу разработчика. Мы используем функцию Sugar.usePrototypes(), которая переносит все нужные функции в прототипы. Если это нам удобно.
Если нет — не используем, а юзаем функции из самого объекта Sugar.

> загадили методами сам объект String
ну это уже субъективно. Лично мне абсолютно не мешает расширение встроенных объектов, если это не создаёт проблем (как с array.prototype и for..in).
Мне более по нраву приём, употребляющийся в Lo-Dash, в Underscore, в underscore.string: простое обрамление «_()» вокруг объекта (или массива, или строки) — и можно не напрягаться насчёт возможных конфликтов.

Естественно, это не относится к es6-shim и другим полифиллам, которые если и ломают работоспособность некоторого кода, то только не готового к появлению именно тех новых возможностей, которые всё равно вскоре появятся в движке и которые заблаговременно обеспечивает полифилл.
Ух ты, упустил такую дискуссию. Тем не менее, откоменчусь, как говорится, for posterity

Представим себе, что sugar и lodash перестали развиваться, sugar'у на смену пришёл не очень совместимый rafinad, а lodash'у — не очень совместимый zlodash (хотя у sugar'а шансов перестать развиваться больше — сами же авторы справедливо подчёркивают, что его нельзя использовать, например, в библиотеках, так что аудитория у него заведомо меньше).

В случае lodash/underscore _-конструкции, требующие корректировки, можно найти в большинстве случаев среднехитровыдуманным grep'ом. В случае же sugar… return hrenRedkiNeSlasche().nafig.map('qqq') — это sugar или нет? Там массив, или что-то другое? Type inference anyone?

Теперь ещё раз рассмотрим авторский справедливый запрет на использование в либах. Откуда они берутся, эти либы и фреймворки? Бывает, пишутся с нуля именно как либы. А бывает, извлекаются из имеющегося кода. Например, компания решает публиковать какие-то инструментальные части своего продукта в виде открытых библиотек. В либах sugar использовать нельзя, ок, значит, его надо оттуда убирать. И вот у нас либа на полмега JS-кода и в ней эти самые упомянутые hrenRedkiNeSlasche().nafig.map('qqq'). Увы :( Хорошее тестовое покрытие может слегка помочь, но боли всё равно будет очень много.

Скажете, надо заранее знать, какие части кода могут пойти в библиотеки, а какие нет? А всегда ли это можно предвосхитить?
Sign up to leave a comment.

Articles