Moment: сделать момент по большей части неизменным

Созданный на 3 июл. 2014  ·  163Комментарии  ·  Источник: moment/moment

Об этом было много дискуссий . Вот предложение:

Следующие изменяемые методы станут неизменными в 3.0.0: utc , local , zone , add , subtract , startOf , endOf , lang , также в duration : add , subtract и lang .

Для начала все методы будут продублированы с вариантами methodNameMute . Нам также нужны неизменяемые варианты с именем methodNameImmute . Начиная с версии 3.0, простые старые методы по умолчанию начнут использовать неизменяемую опцию.

Спорным является:

  • если lang сделать неизменяемым
  • если все геттеры / сеттеры (включая get / set ) тоже должны быть неизменными
  • именование изменяемых и неизменяемых версий методов
  • и, конечно, стоит ли переключиться или просто остановиться на неизменяемом API

Хорошо то, что сегодня мы можем создавать неизменяемые версии методов, а позже решать, что делать. Если мы переключимся, это также будет означать, что ветвь 2.x будет существовать в течение некоторого времени после того, как 3.x отсутствует.

@icambron @timrwood @gregwebs @yang @lfnavess @soswow @langalex

Enhancement

Самый полезный комментарий

Мои два цента заключаются в том, что мы должны либо перейти на полную неизменяемость, либо вообще отказаться от нее. Наличие некоторых методов неизменяемыми ( startOf , add ), а некоторых нет ( year , get ) просто сбивает с толку, и разработчикам придется отслеживать какие есть какие.

Все 163 Комментарий

Мои два цента заключаются в том, что мы должны либо перейти на полную неизменяемость, либо вообще отказаться от нее. Наличие некоторых методов неизменяемыми ( startOf , add ), а некоторых нет ( year , get ) просто сбивает с толку, и разработчикам придется отслеживать какие есть какие.

Я бы также предпочел, чтобы по умолчанию все было неизменным. Не являются ли геттеры уже неизменными?

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

Псевдо неизменяемость

Из-за природы javascript у нас никогда не будет настоящей неизменяемости.

Лучшее, что мы можем сделать, - это создать копию, а затем изменить и вернуть эту копию. Мы можем тщательно обернуть все общедоступные методы, чтобы убедиться, что мы всегда копируем и изменяем, а не просто изменяем, но это не мешает кому-то делать m._d = new Date() или даже m._d.setHours(1) .

Я согласен с @icambron , если мы перейдем к неизменности, это должно быть полное изменение. Любой метод, который мог бы изменить свойство в данный момент, вместо этого создал бы копию момента и вместо этого внесет изменения в копию.

Площадь поверхности API

К сожалению, переключение на псевдо-неизменяемость заключается в том, что необходимо создать много новых API-интерфейсов, если мы хотим по-прежнему поддерживать изменяемость.

Раньше переключение с изменения момента на клонирование и изменение момента было таким же простым, как добавление .clone() в нужное место. Теперь нам нужно создать изменяемые интерфейсы для всех сеттеров, что значительно увеличивает площадь поверхности api.

Сюда входят ~ 20 методов установки, сложение / вычитание, local / utc / zone / tz, startOf / endOf, lang и любые другие методы, используемые в сторонних плагинах.

Проблемы с памятью

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

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

Чтобы отслеживать, какие методы вызываются, я использовал эту небольшую оболочку функции.

for (var method in moment.fn) {
  moment.fn[method] = (function (fn, method) {
    return function () {
      console.log(method);
      return fn.apply(this, arguments)
    }
  })(moment.fn[method], method)
}

Теперь при запуске метода мы можем увидеть, как могут использоваться другие методы прототипа. Не всем этим методам нужно было бы клонировать момент, поэтому я добавил комментарии к тем, которые потребуют клонирования.

moment().isSame(moment(), 'year')
isSame
clone        // clone
startOf      // clone
month        // clone
date         // clone
year         // clone
date         // clone
hours        // clone
minutes      // clone
seconds      // clone
milliseconds // clone
valueOf
local        // clone
zone         // clone
startOf      // clone
month        // clone
date         // clone
year         // clone
date         // clone
hours        // clone
minutes      // clone
seconds      // clone
milliseconds // clone
valueOf

Это 21 копия, которая создается, а затем немедленно отбрасывается. Очевидно, мы могли бы оптимизировать это, используя некоторые внутренние методы, которые являются изменяемыми и открывают только неизменяемые версии, но это значительно усложнит внутреннюю сложность, пытаясь сохранить запись о том, какие моменты все еще нуждаются в клонировании, а какие нет.

Проблемы производительности

Клонирование момента происходит намного медленнее, чем его мутация. Я собрал для этого пару тестов jsperf.

http://jsperf.com/moment-cloning

http://jsperf.com/moment-cloning-2

Я думаю, что второй тест намного лучше отражает потери производительности при переходе на псевдо-неизменяемость. Если мы умножим эти результаты на 21 экземпляр клонирования, упомянутый выше, время выполнения будет намного медленнее.

Я уверен, что мы могли бы оптимизировать путь для клонирования момента, но нам нужно сделать его в 50 раз быстрее, чтобы иметь сопоставимую производительность. Я почти уверен, что это невозможно.

Резюме

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

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

Вообще говоря, начальный .clone () необходим для обеспечения корректности перед выполнением мутации.

Мы не можем делать вид, будто clone () не нужен с текущим API. Главное отличие здесь - выполнение нескольких последовательных мутаций. Этот случай решается путем создания API построителя, в котором все мутации выполняются как мутации для одного клона.

Мне не хватает других распространенных вариантов использования?

Моя первоначальная проблема была endOf методами startOf и endOf . По какой-то причине эти названия для меня были вроде «начни меня за месяц», а не «установи этот момент на начало месяца». Такие методы, как add и subtract , совершенно нормальны в смысле семантики. Совершенно нормально добавить что-то к объекту, не создавая нового.
Лично для меня переименование методов startOf и endOf на что-то вроде toStartOf и toEndOf (например, «переместить этот момент в начало месяца») решило бы проблему. проблема. ИМХО

@gregwebs Извините, я имел в виду set выше.

Я не согласен с @soswow; Я думаю, это должно быть последовательным. На самом деле, я думаю, что toStartOf еще сильнее подразумевает неизменность, как будто это альтернативное представление а-ля toISOString . Что еще более важно, я думаю, что нам нужно иметь возможность делать такие утверждения, как «Установщики моментов изменяют моменты» или «Установщики моментов возвращают копии», а не «ну, для этих методов ...»

О проблемах @timrwood :

То, что объекты JS не будут по-настоящему неизменными, меня не беспокоит. Дело в том, что API предоставляет неизменяемый контракт. Конечно, пользователь может обмануть, возясь с подчеркнутыми свойствами, и обман, как правило, возможен даже в языках, где неизменяемость является основным способом работы.

Что касается поверхности и производительности: я думаю, что нам нужно использовать мутаторы внутри, чтобы не использовать весь процессор и память [1], так что тогда нам придется поддерживать их на каком-то уровне. Тогда мы могли бы также выставить их извне, например, setYear() и т. Д. Это добавляет кучу площади поверхности, но на самом деле не добавляет большой сложности; для неявных мутаторов - внешнее клонирование, внутреннее изменение.

Один из способов взглянуть на это состоит в том, что пользователь должен клонировать свой код, так что Moment с таким же успехом может делать за него. Это действительно представляет проблему с цепочкой в ​​местах, чувствительных к производительности, с которыми можно бороться либо с помощью интерфейса построителя (по идее Грега), либо путем разрешения пользователю просто использовать там мутаторы. Конструктор добавляет кучу сложностей [2], поэтому я думаю, что предпочитаю явные альтернативы мутаторам. Я думаю, что реальность такова, что большую часть времени Moment не используется в ситуациях, требующих высокой производительности, поэтому эти ситуации не обязательно должны быть наиболее удобными с точки зрения API. Я бы предпочел иметь хороший неизменяемый API с перфорированной штриховкой на тот случай, когда он мне понадобится.

[1] Крутые ребята в стране FP решают эту проблему с помощью _структурного обмена_, но здесь это, вероятно, непрактично.

[2] Традиционно люди создают компоновщики, которые представляют собой отдельные объекты, но здесь это будет действительно многословно, поскольку вам придется скопировать весь API-интерфейс установки. Просто плевать, но есть альтернатива: .chain() создает момент клона, на котором просто установлен флаг isBuilding . Тогда внутренние клоны игнорируются, просто возвращая объект для мутации. Затем build() снимает флаг и возвращает этот клон. Проблема в том, что вам нужно, чтобы ваши геттеры кричали о кровавом убийстве, если флаг установлен, иначе люди будут использовать связанные, но не построенные Моменты, которые внезапно становятся мутаторными. Затем вам нужно различать внешние и внутренние геттеры. Блеч. Другой альтернативой является внутренняя декомпозиция функциональности, необходимой компоновщику, в миксин и использование ее как в компоновщике, так и в Moment, но это, вероятно, не работает с точки зрения организации кода.

то, что со мной работало, добавляло дополнительный параметр к функциям, флаг (я назвал себя) для обозначения изменчивости, по умолчанию находится в неизменяемом (вернуть копию или новый объект), и когда я обнаруживаю производительность, я устанавливаю флаг в значение true

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

в моем коде я работаю с массивами массивов (например, таблица, массив строк)
поэтому у меня есть функции для фильтрации, объединения и т. д., которые ранее повторно запускали новый массив с результатом, и я обнаружил, что для получения окончательного результата я несколько раз вызвал одну и ту же функцию, теперь первый вызов - создать копию, а не изменять исходный массив, и следующие вызовы я работаю с той же строкой выпадающего массива, которая мне не нужна

базовый пример, который может быть здесь:
moment.add = function (measure, ammount, self) {
}

moment.add = function (measure, ammount, self) {
var $ moment = self? это: this.clone ();
// актуальный код
return $ moment;
}

Спасибо всем за 2 цента :)

Что касается протокола, я согласен с последним постом @icambron по всем пунктам.

Осталось два больших вопроса.

Более простой - каким должен быть новый API, два варианта:
1.1 методы с разными именами (изменяемые и неизменяемые) year / setYear , startOf / setStartOf
1.2 или builder api chain().mutators().build() , что является не-хакерской версией того, что предложил @lfnavess .

Конструктор api определенно выглядит привлекательнее, но следует позаботиться о том, чтобы объекты не оставались в режиме сборки слишком долго, что добавляет еще один источник проблем для нас и пользователей.

Теперь острая проблема - переход на новую версию. Я вижу здесь два варианта:
Разработчики 2.1 должны переписать свой код (сумасшедшее регулярное выражение может работать в 1.1 и решении уровня AST для 1.2 - если никто не использует year и month в качестве имен своих собственных методов). Python использовал этот подход - мы все видим результат - родился совершенно новый язык!
2.2 возможность всегда включать API сборщика (как сейчас), а также способ деактивировать его для нового кода. Это выглядит более эволюционным, но количество путаницы, которое это может вызвать, того не стоит. Теперь у каждого момента есть два флага: является ли он изменяемым, и, если это так, является ли он строго изменяемым (без геттеров) или переходно изменяемым (геттеры в порядке). Не говоря уже о получении объектов момента в функциях - вы должны проверить, что это за режим, убедиться, что он поддерживается ... какой беспорядок!


И вот сумасшедшая идея, которая пришла ко мне сейчас

Копирование при записи клон

m = moment();
funcIDontTrust(m.clone());  // doesn't actually clone

function funcIDontTrust(m) {
  m.year(2005);  // perform the clone here
  console.log(m);
}

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

Есть несколько способов реализовать с разной производительностью в разных сценариях. Хорошая новость заключается в том, что он обратно совместим, и мы сэкономим нам и нашим пользователям массу усилий. И я считаю, что это важнее, чем изобретать велосипед.

Я не уверен, что мы здесь получаем.

Переход на неизменяемость имеет массу сопутствующих расходов, и, возможно, мне это не хватает, но
Я не вижу сопоставимых преимуществ.

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

Я не думаю, что переход на неизменяемость сделает ошибки менее частыми, это просто
изменить тип ошибок. Пример @ichernev даже показывает, какие именно ошибки
поверхность, которую так же трудно отследить.

m = moment();
funcIDontTrust(m.clone());  // doesn't actually clone

function funcIDontTrust(m) {
  m.year(2005);  // perform the clone here
  // m is still in 2014
  // m.year(2005) created a clone but did not assign it to anything
  // it should be `m = m.year(2005)`
  console.log(m);
}

Вот список плюсов и минусов между изменчивостью и неизменяемостью. Если я что-то пропустил,
дайте мне знать, и я отредактирую этот комментарий.

| Неизменяемый | Мутабельный |
| --- | --- |
| Некоторые разработчики предпочитают это | Некоторые другие разработчики предпочитают это |
| Избегает ошибок при передаче моментов | Избегает ошибок при забывании назначить клонированные моменты |
| С несколькими десятками новых методов api также будет поддерживаться изменчивость | В существующем методе .clone () уже поддерживается неизменяемость |
| | На порядок быстрее |
| | Использует значительно меньше памяти |

Я считаю, что неизменяемость полезна, но не думаю, что она подходит для JavaScript. Я думаю, что неизменяемый интерфейс может иметь смысл для такого языка, как Elm, где ожидается неизменность, но для JavaScript, я думаю, ожидается изменчивость.

Большая часть API для встроенных модулей typeof a === "object" изменяема. Array#push,pop,reverse,sort,shift,splice,unshift все изменяют содержимое массива, а не возвращают новый массив. Все 16 методов Date#setX изменяют свой экземпляр.

Я думаю, мы видим, как многие люди жалуются на изменчивость моментов, но если мы переключимся, я думаю, у нас будет столько же людей, которые будут жаловаться. Это уже произошло с методами eod/sod два года назад.

Посмотрев на кучу старых проблем по изменчивости, я полагаю, что я, вероятно, звучу здесь как неработающий рекорд. С обеих сторон одни и те же вопросы поднимались в течение последних нескольких лет. Я просто хотел убедиться, что в обсуждении был представлен аргумент в пользу сохранения изменяемого API.

@timrwood - это хорошие сравнения, но совершенно очевидно, что вы не нашли времени, чтобы понять неизменный вариант использования. Мы уже обсуждали, почему опубликованные вами сравнения производительности предполагают плохо реализованный API и не имеют смысла.

Сравнение ошибок также недействительно. Поскольку momentjs поддерживает API цепочки, можно было ожидать, что он будет неизменным.

var newM = m.year(2005) // wrong, these are both the same!

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

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

1) Безумный глючный способ (который, вероятно, наиболее распространен): исследуйте весь исходный код, чтобы убедиться, что нет нежелательных мутаций. Напишите модульные тесты, чтобы не допустить появления нежелательных мутаций.
2) Разумный способ (давайте предположим, что это делают все), защитное программирование: не забудьте вызвать функцию clone () перед изменением моей функции.

Благодаря неизменяемому API нам не нужно каждый раз вызывать clone (). Вместо этого мы должны помнить о вызове функции API, которая позволяет нам избежать клонирования, но это всего лишь оптимизация производительности, а не вопрос правильности.

довольно ясно, что вы не нашли времени, чтобы понять неизменный вариант использования

Это несправедливое заявление. Мой аргумент состоит в том, что я вижу преимущества, но не думаю, что они перевешивают затраты.

вы можете спокойно провести мгновение между функциями

нам не нужно помнить о вызове клона

Разве это не вариант использования неизменности? Если в этом есть что-то еще, на что я не нашел времени, пожалуйста, дайте мне знать, но это, кажется, единственный аргумент за последние несколько лет.

@timrwood да, это все.

Но я не вижу от вас знака, подтверждающего, что ваш случай _against_ неизменяемость (ужасная производительность, способствует другому типу ошибки, отсутствующей в изменяемом API) недействителен.

Я думаю, нам следует придерживаться точки зрения ecmascript 5 и, возможно, добавить функцию, которая глубоко замораживает текущий объект, или глобальный флаг, который автоматически создает объекты frezee

http://blogorama.nerdworks.in/preventextensionssealandfreeze/

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

@lfnavess Я подумал о freeze прежде чем упомянуть копию при записи. Проблема в том, что ... никто не использует / не знает об этом, и это не помогает, когда не генерирует исключение (в нестрогом режиме) - это фактически создает сумасшедшие ошибки, которые вы должны отслеживать.

@timrwood Не думаю, что я прояснил свой пример. В строке m.year(2014) // clone here я имел в виду, что внутренне момент фактически создаст клон (выделит больше памяти), и m автоматически укажет на эту новую память. Ну, это в основном означает, что clone() также должен выделить немного памяти оболочки (что-то, что указывает на внутреннее представление даты), я просто не уверен, сколько это можно получить.

Создание неполной версии clone , которая клонирует только интерфейс и возможность изменять базовые данные (с общего хранилища на специфичные для экземпляра) - это действительно зависит от того, насколько дороги объекты Date. Обратной стороной является то, что каждая функция должна выполнять this._storage._d вместо this._d , и я не уверен, что это перевесит преимущество.

Я не получил никаких комментариев о том, как справиться с миграцией существующих библиотек / пользователей на данный момент. Мне не очень нравится ни один из перечисленных выше вариантов.

ИМО, обратная совместимость - самый сильный аргумент против этого. Если мы сделаем это, мы просто должны признать, что это серьезное изменение. Если мы не хотим этого принимать, мы не должны этого делать.

Стоит упомянуть re: perf, что есть также несколько огромных преимуществ, которые вы можете получить от неизменности; это не монотонный перфоманс. Например, вы можете кэшировать вещи на уровне объекта, потому что они никогда не изменятся. Я также думаю, что мы сможем оптимизировать живую хрень из clone() ; AFAIK это включает в себя клонирование даты и копирование как пяти значений; Я думаю, мы должны просто жестко их закодировать, например, newThing._offset = oldThing._offset .

Edit, arg, no - плагины тоже добавляют поля (например, здесь ).

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

Также: идея re: @ichernev о структурном разделении, одна из возможностей - использовать наследование прототипов вместо обертывания объекта общего состояния.

Мы в WhoopInc уже довольно давно участвуем в этой дискуссии. Поскольку обсуждение здесь, кажется, идет по кругу, в эти выходные я потратил некоторое время, чтобы изучить, как может выглядеть неизменная версия момента с API-интерфейсом разработчика. (У меня нет намерения подавать PR на момент, если я этого не приглашаю, поскольку я намеренно вношу более резкие изменения API, чем я ожидал бы когда-либо увидеть реализованными в самом моменте.) Вот результат: https: // github. ru / WhoopInc / frozen-moment

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

Я попытаюсь опубликовать обновленные документы в этом репозитории сегодня вечером, но в основном я просто разделил все методы установки и мутации в отдельный объект-конструктор. Таким образом, использование API может выглядеть как frozenMoment("2014-07-21").thaw().subtract(1, "day").startOf("day").freeze().format("YYYY-MM-DD") . (Хотя в этом конкретном примере было бы более эффективно просто запустить цепочку с помощью построителя, а не инициализировать построитель из FrozenMoment, используя frozenMoment.build("2014-07-21").subtract... )

FWIW, когда я начал использовать момент, я предполагал, что он соответствует принципам FP и будет возвращать одно и то же значение каждый раз, когда я вызываю функцию:

var now = moment();
var yesterday = now.subtract(1, 'days');
var dayBeforeYesterday = now.subtract(2, 'days');

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

Рассмотрим этот псевдокод, который демонстрирует, как я ожидал, что код будет вести себя:

var now = now;
var yesterday = now - 1day;
var dayBeforeYesterday = now - 2days;

Но вместо этого все закончилось так, что мне кажется странным:

var now = now;
var yesterday = now = now - 1day;
var dayBeforeYesterday = now = now - 2days;

На данный момент, хотя это довольно утомительно, я просто тщательно везде .clone() .

var now = moment();
var yesterday = now.clone().subtract(1, 'days');
var dayBeforeYesterday = now.clone().subtract(2, 'days');

IMO, Javascript подвержен тонким ошибкам, и я чувствую, что принципы FP помогают минимизировать эти ошибки.

Я сочувствую, что это трудное решение. Я ценю вашу работу. Moment.js потрясающий.

+1 для 100% неизменности.

Честно говоря, разочарование в том, что он не является неизменным.

+1 за 100% неизменность в версии 3

Определенно должен быть неизменяемый API. Как пользователь других библиотек дат (в частности, .NET DateTime и Joda Time / Noda Time), я интуитивно ожидаю, что метод add не изменит объект даты.

+1 за неизменность

+1 для 100% неизменности

Если будет принято решение о неизменности, я бы потратил свое время на то, чтобы это произошло. Возможно соединение по видеозвонку. Я хотел бы внести больший вклад в открытый исходный код, но мне нужно научиться чему-то новому.

Для меня неизменность предпочтительнее, но это должно было быть сделано с самого начала. Это радикальное изменение. Форк этого проекта, который фокусируется на неизменяемости, был бы лучшей идеей.

@dsherret Вот для чего нужен semver . Мы просто уберем основную версию.

Однако, приложив некоторые усилия, его можно было бы ввести как вариант конфигурации: «Вы хотите, чтобы все было неизменным? Истина или Ложь». По умолчанию будет false.

Неподдерживаемый неофициальный плагин неизменяемого момента ymmv здесь: https://gist.github.com/timrwood/fcd0925bb779f4374a7c

Ха-ха! Я был удивлен, что приехал сюда намного позже и обнаружил, что я был одним из первых сторонников более неизменного API .. :)

И да, я +1 за неизменность для следующей основной версии.

Еще один +1 от меня за неизменный момент по умолчанию.
А вот и мой «imoment»: https://gist.github.com/idrm/a91dc7a4cfb381dca24e (используйте на свой страх и риск!). Просто замените вызовы moment () на imoment (), и этого должно быть достаточно. Все статические вызовы функций moment.xyz () (например, moment.min (), moment.max () и т. Д.) Должны оставаться как есть.

+1 миллион долларов

+1 за неизменность

Могу я также добавить +1 к предыдущему предложению из этой ветки обсуждения, чтобы переименовать некоторые функции, чтобы их было легче читать («startOf» в «toStartOf», «добавить» в «плюс», «месяц» в «withMonth» ", так далее.)? То есть, если вы выберете неизменяемый по умолчанию маршрут. Я часто использую Joda Time, и мне несложно понять, что, например, означает «date.withDayOfMonth (1) .withDayOfWeek (DateTimeConstants.MONDAY)».
Это также не обязательно должно быть в основном JS дистрибутива; дополнение, которое накладывает их поверх ванильного JS, будет работать так же хорошо (черт возьми, я сильно подумываю написать такое дополнение Joda, выровненное по времени, для объединения с моим "imoment" модом).

@ichernev , @icambron , вы приняли решение по этому

К вашему сведению, в последнее время замороженный момент в основном находился в режиме ожидания - я портировал кучу PR из апстрима Moment, но на самом деле не работал ни над одним из других рефакторингов, которые в идеале должны были произойти в этой вилке.

Тем не менее, frozen-moment должен отлично работать, если вам нужен только английский язык по умолчанию. (Все работает для моих вариантов использования, и я сохранил высокий уровень охвата модульными тестами Moment.) Неанглийские языковые стандарты нарушены, потому что я не обновил их после переноса недавно отремонтированных API языковых стандартов Moment.

Как только у нас будет решение для Moment 3.0, я планирую более серьезно поработать над неизменяемостью в Moment или над форком замороженного момента, в зависимости от ситуации. Моя первоначальная цель состояла в том, чтобы исправить поддержку локали и сохранить паритет функций с API Moment 3.0.

+1 за неизменность

+1 за неизменность. А как насчет метода format который также изменяет объект?

+1 за неизменный момент. Js
Или, может быть, форк moment.js? immutable-moment.js? Поскольку это определенно будет переломным моментом.

: 100:
сделать imootables!

+1 в наши дни неизменность - это то, чего я ожидаю от любого хорошего JS API

: +1: Да, пожалуйста, нам бы это очень понравилось. В настоящее время мы разбрасываем .clone () повсюду.

+1 это было бы очень хорошее улучшение

: +1: неизменное все

+1 за неизменный

Сделайте все неизменным. Мне надоело клонировать каждую мгновенную (сейчас) переменную, прежде чем я буду работать с переменной now, а затем снова изменить now.

+1 за неизменность

Я бы не ожидал, что startOf('day') изменится (хотя признаю, что это хорошо задокументировано, если бы я прочитал более внимательно). Это вызвало забавную ошибку в моем приложении.

Я определенно согласен с тем, что большинство операторов moment.js неудобны в своей изменчивости. mmnt.startOf('day') супер-интуитивно понятен в том смысле, что изменяет mmnt .

Я использую moment.js для случаев использования календарного типа с большим количеством циклов и сравнений дат. Я столкнулся с проблемами производительности с помощью clone() и они ужасны. Имея некоторый контроль над тем, что клоны и какие мутирует имеет важное значение для меня и , возможно , другие.
Хотя сначала наличие clone() повсюду кажется неудобным, то, что он делает, предельно ясно и упростило для меня рефакторинг для повышения производительности.

Если каждый метод начинает вслепую использовать внутри себя clone() ради лучшего API, я думаю, мы упустили суть.

мои 2 :-)

@jdurand Я бы предпочел явно видоизменить, чем явно клонировать.

@dsherret Я ничего не возражаю. Меня больше всего беспокоит неявное клонирование, поскольку это очень дорогостоящая операция.
Кто-то упомянул, что установщики должны будут вернуть клонированную копию, и это напугало меня; Это было бы очень неэффективно.

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

Примечание: с этим изменением, я думаю, можно было бы улучшить производительность ... например, клонирование можно было бы исключить, вместо этого ссылаясь на прошлый неизменяемый объект, а затем сохраняя операцию, которая должна быть выполнена для этого объекта (например, add(1, 'days') ). Тогда результат будет вычисляться только при выполнении операций, когда вызывается что-то вроде .toString() , .format() , .toDate() , .day() и т. Д. Это было бы кардинальным изменением, и оно могло бы не стать быстрее ... необходимо провести некоторые модульные тесты для сравнения производительности (кроме того, могут быть другие проблемы, которые я не рассматривал, поскольку я никогда не смотрел ни на один код в moment.js, кроме клонирования).

@dsherret Мне нравится подход _builder _ / _ lazy_; оглядываясь назад, вероятно, он должен был быть построен таким образом с самого начала.
Как вы сказали, я думаю, что лучше всего подойдет неизменяемый форк с учетом совместимости с API.

Еще 2 цента:

  1. Стоит ли нам действительно беспокоиться о производительности, когда момент явно создан для удобства, а не для производительности? Я бы подумал, что синтаксический анализ «года» в m.add («год», 1) намного медленнее, чем клонирование.
  2. Если не будет полной вилки (другое имя, другой документ), поддерживать 2 версии будет настоящей головной болью. Я думаю, что кто-то умный должен придумать идею создания moment.immutable.min.js и moment.min.js из одной и той же кодовой базы ...

С каких это пор мы так боимся ломать изменения? Текущая версия стабильна, и люди по-прежнему могут использовать ее без рефакторинга своей кодовой базы.

Поддержание двух кодовых баз - это боль, она замедляет вас и не стоит того, чтобы иметь изменяемую / неизменяемую версию.

Так что давайте просто возьмем полностью неизменяемый момент, выберем основную версию и покончим с этим: танцоры:

Нашел эту ветку, поскольку я только начал использовать эту библиотеку, но вытаскивал волосы, отлаживая некоторый код и борясь с тем, что мне кажется непредсказуемыми побочными эффектами изменчивости. Хотелось бы увидеть полностью неизменяемую версию библиотеки!

Бесстыдный штекер: Я устал ждать твердого решения здесь. За последние несколько дней я воскресил Frozen Moment и переписал его, чтобы он работал как плагин для самого Moment. Подсказка @wyantb за то, что он помог мне выпустить первый предварительный выпуск за выходные.

Frozen Moment предоставляет неизменяемый тип, который работает так же, как Moment. По сути, неизменяемая версия обертывает функциональность Moment и вызывает для вас .clone() всякий раз, когда это необходимо.

Тем, кому нравятся API-интерфейсы построителя, я предлагаю вам подумать о самом Moment как о очень хорошей реализации объекта-строителя! Frozen Moment добавляет основной неизменяемый тип, который нам всем нужен, и механизм для создания неизменного Frozen Moment из изменяемого Moment.

Для тех, кто просто хочет работать с удобным неизменяемым API - ну, я намерен поддержать и его. Я еще не построил конструктор, который будет напрямую создавать экземпляр Frozen, но он есть в списке TODO . В краткосрочной перспективе обходной путь - создать все с помощью moment().freeze() или moment.utc().freeze() .

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

О, еще одна вещь: я еще не рекламирую это, но экземпляры Frozen Moment должны «просто работать» с большинством плагинов Moment. Просто убедитесь, что все остальные плагины Moment зарегистрировались до Frozen Moment. Если вы найдете плагин, который не работает должным образом с неизменяемыми Frozen Moments, сообщите об ошибке, и я займусь этим.

+1 к неизменности

+1 за неизменный

Кто-нибудь смотрел на реализацию момента поверх Immutable JS ? Это оптимизированная библиотека для неизменяемости в JS, она повторно использует неизменные части неизменяемого объекта, уменьшая проблемы с памятью.

+1
Я только что исправил ошибку трехлетней давности, связанную с этим: https://github.com/Saleslogix/argos-saleslogix/commit/87b35b22c1a42670da369701b15e2bdb3786cabc

Значит, пользователи просят неизменности, но основная команда находит оправдания, чтобы этого не сделать? :п
Да ладно, ребята, это изменение гораздо важнее, чем переписывание кода в ES6 ^^ В нынешнем виде API просто плохой, немного похож на JS Array, где некоторые методы неизменяемы (фильтр, конкат и т. Д.), Но некоторые другие нет (обратный, сортировка), за исключением того, что их ограничение обратной совместимости бесконечно выше, чем для библиотеки.

+1

небольшая ловушка, которая всегда меня ловит (и ИМХО, это веская причина для неизменности):

var today = moment();
for (var i = 0; i < 7; i++) {
   week.push(today.subtract(i, 'days').format('dd').toUpperCase());
}

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

i = 0 = today -0;
i = 1 = today -0 -1;
i = 2 = today -0 -1 -2;
etc

поэтому вам нужно преобразовать его в это:

var today = moment();
for (var i = 0; i < 7; i++) {
            if (i == 0) {
                week.push(today.subtract(0, 'days').format('dd').toUpperCase());
            }
            else {
                week.push(today.subtract(1, 'days').format('dd').toUpperCase());
            }
        }

@faebser отличный пример

+1 за неизменность

+1

@faebser случилось со мной сегодня утром. Двусторонняя привязка + изменчивость Angular делает проблему **, чтобы сохранить даты клонирования, чтобы не изменять текущие.

+1 за неизменность, это стоило мне пары часов.

: +1:

+1 за неизменность

Я немного разрываюсь на эту тему.

Пурист во мне хочет кричать: «+1 за неизменность! Объекты Moment явно относятся к типу ValueObject ».

Однако мы не можем игнорировать этот момент. Js является 13-м по популярности репозиторием javascript на GitHub (и 24 - 111 совпадающих результатов. Даже если мы сможем предоставить разработчикам приложений постепенный способ реализации неизменяемой версии момента, это вызовет огромный беспорядок среди его зависимостей.

@ichernev Возможно, более скромное предложение: можно ли посвятить небольшую часть страницы документации моменту разговору о изменчивости и неизменности? Вы можете кратко изложить свою официальную позицию по теме и, возможно, добавить краткое изложение аргументов, разместить ссылку на эту ветку или, если вы хотите, чтобы конкретный ввод в обсуждение мог работать как CTA.

Прямо сейчас на странице документации не упоминается термин «неизменяемый». Поиск в Google «момент неизменяемый» приведет вас на эту страницу, но мне потребовалось два часа чтения, и я все еще не уверен в вашей текущей позиции по этой теме. Было бы здорово, если бы главный хит Google по «неизменности момента» дал быстрый ответ о будущем неизменности момента :)

Процитирую @ jehoshua02 :
«Сочувствую, что это трудное решение. Я ценю вашу работу. Moment.js великолепен».

Вот мое предложение. Вместо того, чтобы сделать базовый момент неизменным, добавьте фабрику moment.immutable . Это было бы свойством функции moment и заключало бы ту же самую точную подпись API, что и moment , но неизменяемую.

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

РЕДАКТИРОВАТЬ: Похоже, WhoopInc / frozen-moment - это именно то, что я ищу.

Критические изменения

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

Похоже, я тоже столкнулся с этой проблемой.

http://stackoverflow.com/questions/33002430/moment-js-formatting-incorrect-date

Так что я полностью за неизменность во всем.

+1 За неизменность

Просто потерял вечер из-за этого удивительного и неожиданного поведения.
Еще один +1 за неизменность с соответствующим изменением основной версии, чтобы было понятно.

+1 За неизменность

+1 за полную неизменность.
Общее количество часов, потерянных из-за «иногда изменчивого, иногда неизменного», должно быть довольно большим.

Да я серьезно. Кого волнует производительность в библиотеке datetime? Как .. правда? Я предполагаю, что 99,9% пользователей не делают ничего, что даже удаленно требует хорошей производительности. Обычно вы обрабатываете пару свиданий, а в худшем случае - несколько сотен. Те немногие пользователи, которые обрабатывают миллионы дат в секунду, могут использовать оптимизированные изменяемые точки API.

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

+1 за неизменность. Это стоило мне пары часов.

Частично проблема заключается в том, что имена методов, такие как .startOf() , не подразумевают мутации базового объекта.

Я столкнулся с узкими местами производительности с помощью Moment, поэтому могу заверить вас, что иногда это может происходить.

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

Этот спор давно улажен в мире Java. Неизменяемые даты победили, и самая популярная реализация (JodaTime) в конечном итоге стала частью стандартной библиотеки в Java 8.

Работа с LocalTime Java 8 была одним из тех "пощечин": "Почему мы _ всегда_ этого не делали?" моменты. Я редко проповедую технологии, но, честно говоря, я не вижу никаких плюсов в изменяемых объектах даты.

Так что да ... Я ненавижу, что эти потоки наводняются +1, но правда в том, что кто-то другой собирается создать неизменяемую библиотеку дат JS, если Moment этого не сделает.

Недавно я наткнулся на новый модуль npm, предназначенный для переноса большей части JodaTime API (например, дат Java 8) на JS.

Это принесет такие вещи, как неизменяемость, LocalDate и LocalTime для узла и браузера.

После работы с этими концепциями на Java все остальное кажется беспорядочным и подверженным ошибкам.

Ссылка?

Пт, 11 декабря 2015 г., 16:30 Эндрю Шмадель [email protected]
написал:

Недавно я наткнулся на новый модуль npm, предназначенный для переноса большей части
API JodaTime (например, даты Java 8) в JS.

Это принесет такие вещи, как неизменяемость, LocalDate и LocalTime, в
узел и браузер.

Поработав с этими концепциями на Java, все остальное кажется глупым.
и подвержены ошибкам.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/moment/moment/issues/1754#issuecomment -163964349.

Wout.
(набрано на мобильном телефоне, извините за лаконичность)

Поскольку я еще не вмешивался, я просто заявляю, что я за неизменность в момент 3.0. В первую очередь потому, что я пришел из школы мысли DDD, где такие объекты, как moment , будут рассматриваться как _value objects_ и, следовательно, лучше всего реализованы как неизменяемые.

Даже если производительность значительно снизится, это все равно правильно. Момент должен естественно вписываться в дизайн других. Интуитивно понятный API превосходит perf, а мутация не интуитивно понятна для объектов значений (IMHO).

Я также думаю, что момент 3.0 должен устранить его зависимость от объекта Date , но это обсуждение для другого потока.

Я полностью согласен с @ mj1856 здесь.

Я использовал Object.freeze в моментальных экземплярах, и это в целом достигло того, что мне было нужно; за исключением того, что я только что обнаружил, что следующее не работает:

let now = Object.freeze(moment());
if (now.isSameOrBefore(anotherTime)) { // throws exception
}

Исключение:

TypeError: Can't add property _isValid, object is not extensible
 at valid__isValid (C:\git\quick-test\node_modules\moment\moment.js:93:24)
 at Moment.moment_valid__isValid [as isValid] (C:\git\quick-test\node_modules\moment\moment.js:2195:16)
 at Moment.isSame (C:\git\quick-test\node_modules\moment\moment.js:1945:44)
 at Moment.isSameOrBefore (C:\git\quick-test\node_modules\moment\moment.js:1962:21)

Можно ли это исправить, чтобы при желании можно было использовать Object.freeze ?

@wmertens, я бы предположил, что это он: https://github.com/pithu/js-joda

@ichernev , @ mj1856 , поскольку я

Я не уверен, был ли я единственным препятствием на пути к этому, но мне комфортно двигаться вперед с неизменностью в версии 3.0.

@gabrielmaldi @wmertens Ага. Вот и все. Приносим извинения за свой непоследовательный комментарий - я явно нажал кнопку «Отправить» в наполовину написанном сообщении.

Чтобы собрать некоторые из моих разрозненных мыслей:

  • Очевидно, что есть некоторый интерес к неизменяемым объектам даты для JS. Существуют зрелые библиотеки неизменяемых дат на нескольких других языках, и в JS наблюдается большая общая тенденция к неизменным объектам ( immutable.js имеет 10 500 звезд, если это так). По крайней мере, я думаю, что это заслуживает проверки концепции.
  • Несмотря на этот интерес, похоже, было написано очень мало кода. js-joda кажется первой серьезной попыткой написать неизменяемую библиотеку дат для JS.
  • Неизменяемые моменты были бы огромным переломным моментом, который поднимает некоторые философские вопросы. Хотя я бы не хотел потерять поддержку очень большого сообщества MomentJS, для тех из нас, кто интересуется неизменяемыми датами JS, не обязательно будет ужасно сделать полный перерыв и внести свой вклад в js-joda вместо того, чтобы пытаться продвинуть довольно радикальные изменения в Moment (зрелая библиотека с большой и устоявшейся пользовательской базой).
  • Кроме того: js-joda еще очень молод, и неясно, каковы цели и намерения автора в отношении библиотеки. В частности, ему нужно выбрать лицензию, и мы, возможно, захотим рассмотреть, будут ли удовлетворены потребности типичного разработчика JS с помощью точной повторной реализации Joda Time или JSR-310.

+1 за неизменность и более разумный код, который в результате получится.

Это будет серьезное усилие, поэтому искреннее спасибо тем, кто будет (и делал), чтобы это произошло.

Moment достаточно широко используется, и я думаю, что было бы целесообразно пойти с чем-то, близким к следующему, если предположить, что он реализован аналогично https://github.com/WhoopInc/frozen-moment @butterflyhug.

3.x: неизменяемый как опция, по умолчанию false, и для глобального экспорта момента установлен флаг, который будет иметь значение true; console.warn при загрузке библиотеки (в режиме разработки)
4.x: неизменяемый как опция, по умолчанию true, флаг все еще доступен для установки как false; console.warn о расписании для 5.x (в режиме разработки)
5.x: неизменяемый как единственный способ

Сделайте страницу впереди и в центре, описывающую долгосрочное видение неизменности - скажем, один крупный выпуск в год по схеме 3.x / 4.x / 5.x, которую я изложил, - и я думаю, что это даст разумный сумма для всех, кто пострадал, чтобы обновить свой код.

Несколько наблюдений:

  1. Я создал WhoopInc / frozen-moment в надежде, что куча людей здесь, возможно, захочет построить что-то с его помощью, как способ найти проблемные точки в текущей экосистеме, где неизменяемость сломает плагины и т. Д. Пока что мало кто сделал это. , что сделало меня менее заинтересованным в работе над замороженным моментом и / или пропагандой сообщества, чтобы помочь авторам плагинов поддерживать неизменные моменты.

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

  1. Если момент реализует неизменяемость в версии 3.0, кому-то будет довольно просто написать и поддерживать оболочку для реализации изменяемого API момента 2.x поверх неизменяемого API 3.x. Концептуально это на самом деле будет очень похоже на замороженный момент: везде, где этот замороженный момент неявно clone() s, эта оболочка изменяемости вместо этого неявно изменяет свою внутреннюю ссылку на новое неизменное значение момента. Это также может облегчить переход для людей, использующих момент в больших базах кода.
  2. При желании я был бы готов помочь обдумать возможные проблемы и реализовать неизменяемость в момент 3.
  3. js-joda будет напрямую переносить JSR-310 в JavaScript с использованием лицензии BSD .

@butterflyhug - Спасибо за

Я не знаю, у скольких других людей могли быть такие же мыслительные процессы.

Мне любопытно, думают ли здесь люди, что неизменяемость следует исследовать в сочетании с понятием разрыва зависимости от объекта Date (или даже добавлением какой-то ленивой оценки) по соображениям производительности.

Я бы посоветовал делать вещи постепенно, @schmod. Это уже (по-видимому) большое изменение

@RobertMcCarter Да, я планирую поддерживать замороженный момент в обозримом будущем, если / пока не будет реализован какой-либо вариант неизменяемости в основной библиотеке - в значительной степени потому, что я лично использую его для некоторых вещей, которые, как я ожидаю, будут поддерживая какое-то время. Тем не менее, мои варианты использования не охватывают всю экосистему Moment, поэтому я полагаюсь на отзывы и использование других людей, чтобы помочь определить, что важно.

+1 за неизменность после получаса, потраченного на выяснение того, что произошло с моим приложением после первого использования endOf (). Конечно, я не читал внимательно документацию, я просто предполагал, что метод с таким именем вернет, например, конец месяца и не затронет экземпляр момента. Честно говоря, это сюрприз, и мне кажется смешным, что этого не происходит, или, может быть, моя голова слишком привыкла к - по моему мнению - огромным преимуществам наличия - в основном - неизменяемого API.

+1 за неизменность :)

Меня не волнует неизменность, оставьте эту прекрасную библиотеку в покое!

@ es6Test На каком основании вы не согласны с неизменностью? Есть ли у вас какая-либо конкретная причина, кроме сопротивления изменениям?

+1
Я думаю, что это упростит использование библиотеки, если она будет неизменной, мой код полон метода .clone (), а иногда изменчивость очень затрудняет поиск ошибок.

+1 Пожалуйста, побольше неизменности ^ _ ^

@danpantry Сделав еще несколько приложений, я передумал. Я бы предпочел неизменность.

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

@ es6Test Просто используйте let если вам это действительно_ не нравится?

let date = moment()
// with immutability
date = date.add(5)

Я тоже за неизменность. Это единственная особенность библиотеки Python datetime которая действительно заставляет ее сиять. Вы можете бросать предметы, не беспокоясь о том, что что-то их изменит, как и в случае с символьными строками.

В мире React / Redux неизменность имеет первостепенное значение. Я уже столкнулся с некоторыми грубыми проблемами, потому что момент не является неизменным по своей сути. Производительность здесь не имеет значения, поскольку ее можно уменьшить. Библиотека ImmutableJs от Facebook доказывает, что неизменяемость может быть реализована без ущерба для производительности.

Я также буду +1 к неизменяемости на всем пути. До тех пор вы не получите никаких преимуществ от неизменности, так что нет смысла идти наполовину.

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

Команда хотела дать обновленную информацию по этому поводу, так как мы вызвали такой большой интерес.

В настоящее время мы хотим, чтобы вы знали, что мы услышали ваши опасения. Вся команда сопровождающих согласна с тем, что если бы мы писали библиотеку с нуля, мы бы сделали ее неизменной. Однако сейчас это не так.

В настоящее время у нас есть 4 миллиона загрузок NPM в месяц, а также бесчисленное количество пользователей, которые рассчитывают получить момент по другим каналам. У всех этих пользователей есть код, который ожидает, что момент будет изменчивым, как и сегодня. Кроме того, у нас есть много плагинов, которые зависят от изменяемого момента.

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

  • Почему плагин замороженного момента не отвечает вашим потребностям?
  • Вам просто нужен неизменный API (API, который всегда возвращает клон), или нам по какой-то причине нужно внутренне действительно не изменять объекты?
  • Отвечает ли добавление второго неизменяемого API к текущему коду вашим потребностям?

Проблема с плагином замороженного момента заключается в том, что он поддерживает, а не отказывается. Каждый
moment () нуждается в .freeze (), чтобы быть неизменным.

Вся суть неизменности в том, что когда у меня есть объект X, я знаю, что
если я явно не сделаю его изменяемым, он должен быть невосприимчивым к изменениям.
Любая публичная функция, которая позволяет мне изменять объект внутри без
явная изменчивость проблематична.

Я думаю, что одно решение - это сделать несколько вещей:

  1. Добавить второй неизменяемый API в текущий код
  2. У вас есть глобальный параметр moment (), где, если он установлен в неизменяемый режим, все
    Созданные экземпляры moment () являются неизменяемыми, если выполняется попытка изменяемого вызова,
    не будет видоизменяться и вместо этого будет выдавать соответствующее сообщение об использовании неизменяемого
    вызовы api.

Я думаю, это удовлетворит всех. Что вы думаете?

В понедельник, 23 мая 2016 г., в 12:11, Мэгги Пинт [email protected]
написал:

Команда хотела рассказать об этом, так как у нас было так много
интерес.

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

В настоящее время у нас есть 4 миллиона загрузок NPM в месяц, а также
бесчисленное количество пользователей, надеющихся получить момент через других
каналы. У всех этих пользователей есть код, который ожидает, что момент будет изменен как
это сегодня. Кроме того, у нас есть много плагинов, полагающихся на момент, когда
изменчивый.

Код достаточно легко написать, но поддержка требует такого рода
изменения трудно осуществить, поскольку небольшая команда делает это в свободное время
время. Тем не менее, мы готовы это рассмотреть. Однако нам интересно:

  • Почему плагин замороженного момента не отвечает вашим потребностям?
  • Вам просто нужен неизменный API (API, который всегда возвращает
    clone), или нам по какой-то причине нужно внутренне действительно не мутировать
    объекты?
  • Будет ли добавление второго неизменяемого API к текущему коду соответствовать вашему
    потребности?

-
Вы получили это, потому что прокомментировали.
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/moment/moment/issues/1754#issuecomment -221062274

Эрик Лау из аккаунта Gmail.

Спасибо за ответ @maggiepint.

  1. Несколько проблем с плагином замороженного момента: это не по умолчанию, для его использования требуется дополнительная работа, меньше шансов, что он будет активно поддерживаться, я предполагаю, что у него есть снижение производительности (вероятно, очень небольшое) по сравнению с тем, что было построен как неизменный. Я думаю, что самая большая проблема - это забыть его использовать, особенно в больших проектах с большим количеством инженеров.
  2. API не должен иметь побочных эффектов. Возврат клона - это хорошо, но если вы также измените исходный объект, это будет побочным эффектом. Следующий код не должен изменять начало при объявлении конца:
start = moment();
end = start.add(10, 'minutes');
  1. Вы имеете в виду наличие таких функций, как «immutableAdd» в дополнение к «add»? Если да, то технически да, особенно если вы создадите оболочку для использования неизменяемых функций с теми же именами:
import "moment/immutable";
start = moment();
end = start.add(10, 'minutes'); // immutable version of add

На мой взгляд, этот подход дает возможность изящного обновления для тех, кто хочет использовать неизменяемый API - существующий код по-прежнему будет работать, никто не будет принудительно вставлен и требует меньших изменений для тех, кто действительно хочет использовать неизменяемый API.

У нас есть все намерения избавить код от побочных эффектов. Базовым шаблоном было бы подключиться к текущим функциям, заставить их вызывать clone, а затем работать с этим клоном.

Однако технически, если вы создаете действительно неизменяемый код, объекты должны быть построены со значениями, которые не изменятся. Однако это усложнит внесение этого изменения. Намного проще вызвать clone, а затем делать то, что мы делали раньше.

Я поддерживаю идею Дрю:

импорт "момент / неизменяемый";
начало = момент ();
end = start.add (10, 'минут'); // неизменяемая версия добавления

Это было бы здорово, поскольку это неизменный отказ и никаких изменений в
имена функций.

В понедельник, 23 мая 2016 г., в 12:53, Мэгги Пинт [email protected]
написал:

У нас есть все намерения избавить код от побочных эффектов. Базовый
шаблон будет подключаться к текущим функциям, заставлять их вызывать clone,
а затем оперируйте с этим клоном.

Однако с технической точки зрения, если вы создаете действительно неизменяемый код, объекты
должны быть построены со значениями, которые не изменятся. Это будет
однако усложняют это изменение. Намного проще
вызовите clone, а затем сделайте то, что делали раньше.

-
Вы получили это, потому что прокомментировали.
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/moment/moment/issues/1754#issuecomment -221076796

Эрик Лау из аккаунта Gmail.

@ ericlau-solid

  1. У вас есть глобальный параметр moment (), где, если он установлен в неизменяемый режим, все
    Созданные экземпляры moment () являются неизменяемыми, если выполняется попытка изменяемого вызова,
    не будет видоизменяться и вместо этого будет выдавать соответствующее сообщение об использовании неизменяемого
    вызовы api.

Это сломается, если 2 библиотеки на странице ожидают разное поведение в данный момент. Например, вы используете datepicker, который ожидает изменяемый момент, а ваш собственный код ожидает неизменный - это не сработает.

Имея неизменный api (аля замороженный момент)

Это также не идеально, потому что никакие плагины не будут работать с ним. На самом деле, нет способа ввести неизменяемость И сохранить работоспособность всех существующих плагинов. Плагины либо вообще не будут работать, либо не будут работать с неизменяемыми моментами, прежде чем кто-то потратит время на их работу.

импорт "момент / неизменяемый";

По сути, это предлагает другую библиотеку с аналогичным интерфейсом. Конечно, это не сломает код, но, скорее всего, вызовет путаницу и заставит какой-то проект установить 2 версии (например, datepicker возьмет изменяемую версию, а ваш код - неизменяемую).

Лучший вариант - создать API, похожий на текущий, но с неизменяемыми объектами. Вилка может быть в порядке. В конце концов, это путь свободных программ.

Вариант «добавить второй API / опубликовать подмодуль» лучше всего подходит для совместимости, потому что разработчики смогут обновлять свой код постепенно. Если это вообще возможно, значение moment() (через import moment; в модуле-land или moment global в сборке браузера) вообще не должно меняться, потому что есть тонна устаревшего кода.

ИМО, решение, которое позволило бы следующее, было бы идеальным:

import moment from 'moment';
import {immutable as immoment} from 'moment';

var a = moment(); // mutable moment
var b = moment().immutable(); // immutable moment
var c = immoment(); // also an immutable moment; shorthand

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

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


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

Я также не думаю, что это разумное требование / предположение, чтобы изменяемые и неизменяемые API были идентичны. Мы должны стремиться сделать процесс обновления как можно более плавным, но не должны ограничиваться какими-либо неудобными синтаксисами.


Я также думаю, что есть много места для дискуссий / споров о том, как будет выглядеть «неизменный» API. Выкройка строителя? Создание экземпляра конструктора? Ценный объект? Реализовать текущий API, но могут ли какие-либо методы установки возвращать клон?

Моя единственная просьба заключается в том, чтобы в новом API было четко и недвусмысленно указывать, с каким моментом мы работаем. ИМО, freeze не проходит этот тест и предлагает небольшую защиту, кроме вызова clone() каждый раз, когда я провожу минутку.

По сути, это предлагает другую библиотеку с аналогичным интерфейсом. Конечно, это не сломает код, но, скорее всего, вызовет путаницу и заставит какой-то проект установить 2 версии (например, datepicker возьмет изменяемую версию, а ваш код - неизменяемую).

Не отдельная библиотека, а тонкая обертка вокруг той же библиотеки. Для этого потребуется установить только одну версию момента. Вы можете импортировать «момент / неизменяемый», а средство выбора даты может без проблем импортировать «момент» в один и тот же проект.

Могут возникнуть проблемы с взаимодействием с плагинами, которые принимают или возвращают момент, если они не обновились для обработки неизменяемых моментов.

Допустим, вы передаете неизменяемый момент плагину, который в настоящее время рассматривает его как изменяемый. Пока плагин не будет обновлен, должен быть способ преобразования в изменяемый, прежде чем плагину будет предоставлен момент. В идеале это было бы нерекомендуемо после того, как у сопровождающих проекта будет немного времени на поддержку неизменяемости. Также, вероятно, потребуется способ определения неизменяемости (для авторов плагинов).

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

@maggiepint да, я понимаю вашу точку зрения, но я думаю, что это может быть слишком большой прыжок, чтобы сделать это. Лично меня бы устроил подход, при котором просто clone скрывается за занавеской. Особенно пока прорабатываются изгибы.

@tacomanator , я тоже хочу этим заниматься. Переделывать все, чтобы оно стало действительно неизменным внутренне, не очень разумно.
Я просто не знал, ХОТЯТ ли люди этого по какой-то причине.

@schmod Не могли бы вы вкратце freeze является ясным и недвусмысленным API?

Если имя функции слишком красивое, я был бы рад рассмотреть аргумент в пользу переименования методов Frozen Moment как проблему в этом репо. С другой стороны, если вы не думаете, что возможно преобразование из изменяемого в неизменяемый (и обратно), то я подозреваю, что это может вызвать здесь некоторое обсуждение - хотя обратите внимание, что я также был бы готов взять Frozen Moment в этом направлении, если мы получим приблизительный консенсус, что это будет лучший API.

@maggiepint Правильно ли я прочитал «добавить второй неизменяемый API к текущему коду» как в основном объединение части или всего Frozen Moment с основной библиотекой? Если бы это было полезно, я был бы рад помочь перенести Frozen Moment или некоторые из его идей в организацию момента (либо как официальный плагин, либо как часть основной библиотеки) и помочь с его обслуживанием в этом новом контексте.

@butterflyhug Вы говорите именно то, о чем думал

@butterflyhug

Я думаю, что freeze - хорошее имя, просто отстой, что нужно помнить о его использовании после _каждого_ единственного_ вызова момента.

Я также думаю, что import 'moment/immutable' имеет те же проблемы, об этом легко забыть.

Честно говоря, вы следите за семвером, я думаю, что правильный подход - сделать все использование неизменяемым _по умолчанию_ и выпустить это изменение как собственную основную версию с планом больше не поддерживать более старые версии по прошествии определенного периода времени (12 месяцев?). Новые функции / исправления могут быть объединены в обе версии, неизменяемые и изменяемые, с планом миграции, предоставляемым пользователям, использующим изменяемую версию.

По прошествии вышеупомянутых 12 месяцев старые версии _по-прежнему_ будут работать, но не получат никаких TLC.

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

Еще одним потенциальным недостатком этого подхода является то, что пользователи используют этот сценарий из CDN и не указывают явную версию (по какой-либо причине), что может привести к поломке их сайтов в случае выпуска обратно совместимого API. Все, что я могу сказать, это «я же вам сказал», но я понимаю, что на данный момент это может быть неприемлемым риском.

Наличие двух версий одной и той же библиотеки будет проблемой только в том случае, если вы полагаетесь на глобальный объект, и на самом деле нет другого удобного пути, кроме как просто продолжать использовать freeze() .


TL; DR: похоже, что проблема, которую вы пытаетесь решить, решена с помощью semver, который вы уже используете. Почему бы просто не использовать его так, как нужно? Основная версия для критических изменений. Единственный случай, когда это прерывается, - это когда вы полагаетесь на глобальную переменную moment и используете CDN, но любое изменение, которое мы делаем здесь, все равно нарушит это

Я также голосую за выпуск semver и immutable 3.0.

Я не возражаю против имени freeze , но считаю, что по сути своей проблематично то, что трудно делать безопасные предположения о том, заморожен ли момент или нет. ( Object.freeze() имеет аналогичную проблему)

Неизменяемый момент не должен быть незамерзаемым, и никогда не должно быть никаких сомнений в том, заморожен он или нет. Это может быть достигнуто с помощью строгого варианта паттерна построителя (т.е. объект _only_ имеет сеттеры до тех пор, пока не будет вызван .build() , после чего у него _только__ есть геттеры) или «заморозить» момент, как только он создается, и все сеттеры возвращают клон.

Например:

/* BUILDER PATTERN */
var bldr = moment.immutable()
  .hours(5)
  .minutes(30)
  .seconds(25);

bldr.hours();  // throws exception.  builder has no getters

var time = bldr.build();

time.hours(); // 5
time.hours(6); // throws, OR returns a clone

/*  A more explicit variant:  */
var bldr = moment.immutable()
  .setHours(5);

bldr.getHours; // undefined

var time = bldr.build();
time.getHours(); // 5
time.setHours;   // undefined
/* VALUE OBJECT */
var time = moment.immutable()   // 00:00:00
  .hours(5)       // new object => 05:00:00
  .minutes(30)    // new object => 05:30:00
  .seconds(25);   // new object => 05:30:25

/*  Same thing, but more efficient:  */
var time2 = moment.immutable(5,30,25); // 05:30:25

time.hours();   // 5
time.hours(6);  // new object => 06:30:25

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

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

Похоже, что во втором примере намного больше накладных расходов, потому что мы создаем (и отбрасываем) множество объектов. Но есть много возможностей для оптимизации. Современный GC довольно хорош; может помочь ленивая оценка; мы могли бы сделать объекты Moment максимально легкими (отбросив базовый Date ) и т. д. (для некоторого сравнения этот шаблон мало чем отличается от способа обработки строк в JavaScript)


Я поклонник semver, но в случае использования браузера критические изменения проблематичны, потому что без модуля-загрузчика невозможно иметь две версии момента на одной странице.

Как упоминалось ранее, существует масса устаревшего кода, который зависит от Moment. По крайней мере, нам нужен выпуск, поддерживающий оба шаблона, чтобы обеспечить плавный переходный период.

+1 за составные методы, возвращающие новые моменты. Меня даже не волнует, неизменны ли они. Просто дайте мне композицию, чтобы я мог связать методы вместе или назначить измененный момент в одной строке (вместо 2).

@alexyuly, почему у вас не работает клон? Если вы хотите создать встроенный код, вы можете сделать что-то вроде:

var a = moment();
var b = a.clone().subtract(1, 'week').startOf('day');

Или как там.

@maggiepint Что ж, я чувствую себя глупо, похоже, вы могли бы все время составлять методы. Спасибо за совет. Может быть, в документации внесем ясность? например http://momentjs.com/docs/#/manipulating/start -of / <- никаких упоминаний о возвращаемом значении.

Небольшое обновление - это сообщение в блоге - МОЯ позиция по этому вопросу на данный момент: https://maggiepint.com/2016/06/24/why-moment-js-isnt-immutable-yet/

Я не говорю от имени остальной команды, но они это видели, и я бы в целом сказал, что мы все находимся в одном месте.

@maggiepint отличные и очень

Спасибо за это. Неизменяемость - это король redux, поэтому я обязательно перейду на js-joda. Я все еще могу считать момент относительным временем.

Эрик Лау - Gmail

Пт, 24 июня 2016 г., 11: 12–07: 00, «Мэгги Пинт» [email protected] написала:

Небольшое обновление - это сообщение в блоге - МОЯ позиция по этому вопросу на данный момент: https://maggiepint.com/2016/06/24/why-moment-js-isnt-immutable-yet/

Я не говорю от имени остальной команды, но они это видели, и я бы в целом сказал, что мы все находимся в одном месте.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub или отключите чат.

Еще несколько типичных ошибок / недоразумений, вызванных мутацией: http://stackoverflow.com/questions/26131003/moment-js-start-and-end-of-given-month

+1 для этого, но на самом деле с Redux я обнаружил, что это удивительно небольшая проблема, потому что я вообще не помещаю экземпляры Moment в объект состояния Redux. Только строки даты или отметки времени, и я использую Moment в методах рендеринга только для преобразования строк даты в другие строки.

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

Стараюсь сообщить вам последнюю информацию об этом в эти выходные. У нас есть план, но мне нужно убедиться, что он все сработает, прежде чем я возьму на себя его. К сожалению, на следующей неделе я переезжаю из Миннеаполиса в Сиэтл, так что это может на время замедлиться, но я хочу двигаться вперед.

Небольшое обновление в рамках подготовки к более крупному обновлению, поскольку я заметил, что это сообщение в блоге все еще получает некоторый трафик. В настоящее время я переделываю сборку момента, чтобы использовать Babel. Это заставляет нас добавить плагин @butterflyhug очень любезно помогает нам в этом. Кроме того, я встречаюсь с Джоном-Дэвидом Далтоном из LoDash (мы оба работаем в Microsoft), чтобы обсудить стратегию внедрения официального плагина, как он уже сделал это с функционалом LoDash. Скоро появится длинный пост в блоге и RFC.

@maggiepint при официальной поддержке замороженного момента, планируете ли вы обратиться по адресу https://github.com/WhoopInc/frozen-moment/issues/20?

Я думаю, что этот подход к неизменяемости достаточно хорош, если каждый вызов moment() по умолчанию возвращает замороженный момент, и разработчикам не нужно помнить о вызове .freeze() каждый раз.

@gabrielmaldi Хороший вопрос. Я пишу RFC (должен быть выполнен в любой момент), и да, моя явная цель - предоставить лучшую историю для использования только неизменяемыми. Мое предложение совпадает с моим комментарием к WhoopInc / frozen-moment # 20 с учетом статических методов. Я опубликую ссылку на свой RFC здесь и в этом выпуске, когда я открою свой PR для репозитория RFC, и мы, безусловно, будем приветствовать отзывы сообщества о предложении в то время.

Я закончил писать черновик RFC и открыл PR .

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

Краткое изложение RFC с нашими основными вопросами, на которые необходимо ответить: https://maggiepint.com/2016/07/16/immutability-its-happening/

@maggiepint Я попытался


Меня больше всего беспокоит то, что эти изменения реагируют на непропорционально громкую и выразительную часть сообщества - избегая тихого оплота обычных разработчиков, которые даже не подозревают, что это обсуждение происходит.

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

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

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

Я также думаю, что вам также следует быть очень осторожными, чтобы подтвердить важность этого изменения в реальном выражении. Интересно, следует ли вам выпустить это изменение как плагин или оболочку и внимательно следить за его внедрением в течение нескольких месяцев, прежде чем объединять его в магистраль. Если неизменяемость была чрезмерно представлена ​​в качестве нишевой проблемы, вы найдете способ удовлетворить этих голосовых пользователей, не меняя курс библиотеки в целом.

Как первый пользователь, я закончил здесь через некоторое время, потеряв startOf endOf. Эти методы на удивление видоизменяются!

+1 за полную неизменность

Возможно, другое решение - сделать до боли очевидным, что объекты в momentjs изменяемы . Документация упоминает об этом в разделе клонирования, но этого недостаточно.

Другое решение. Если вам нужна изменчивость, используйте объектно-ориентированные концепции и создайте объект с помощью ключевого слова NEW по сравнению с шаблоном фабрики moment ().

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

Все, кого я видел, будучи новичками в моменте, попадают в ловушку мутаций «моментов».
Даже после 3 лет использования момента мне все еще приходится говорить себе: «О, черт возьми, ты используешь .startOf здесь ... лучше проверьте дважды, если тебе нужна копия».

Текущее поведение не является интуитивным, и это давно назрело.
Попробуйте изменить array.filter / map и посмотрите, насколько это весело.

Касательно...
Производительность / память: я никогда не связывал более двух функций в один момент времени, и обычно это .set().get()
Псевдо-неизменяемость: потребуется много-много поколений, пока не выйдет java-pass-by-ref-gen.

Мне нравится идея @AdamHess о выборе, ищете ли вы ООП или неизменяемость.

Мои два цента о том, почему мы запутались, таковы: возвращаемые значения. Если бы moment.add('1', 'days') возвращал undefined, как обычно делают изменяемые функции в JS, то путаница исчезнет. Возврат того же объекта, по крайней мере для меня, означает, что у меня есть новая копия. Конечно, это нарушит цепочку.

Я думаю, что существует низкая вероятность возникновения проблем с использованием памяти для большего числа разработчиков (за исключением особых случаев использования). Но изменчивость Момента уже меня укусила. Даты следует рассматривать как значения, такие как строка или число.

+1 для неизменяемого по умолчанию

Кстати, такая же проблема существует и для PHP. Вы хотите быть похожими на PHP ?! 😆

В PHP они решают эту проблему, предоставляя DateTimeImmutable (в дополнение к обычному DateTime ).

Если мы не изменим поведение по умолчанию, чтобы оно было неизменным, мы должны хотя бы рассмотреть альтернативный API первого класса, такой как imoment / momenti (или что-то еще). Я бы буквально всегда использовал это (через изменяемый API), и я надеюсь, что любая другая библиотека, которую я использую, также будет использовать неизменную версию / API.

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

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

@ngerritsen Я считаю, что лучший доступный вариант - moment.duration(existingDuration) .

Re: реализация, # 3548 все еще активен в PR. Надеюсь, что осталось не так много работы на уровне кода, но никогда не помешает иметь больше глаз для проверки больших изменений. Нам также нужно поработать над документацией и т. Д., Прежде чем мы сможем сделать резкое изменение основной версии, которое будет необходимо для выпуска подобного изменения. Если вы хотите помочь с любым из этого списка, я уверен, что мы будем признательны. 😀

Просто потратил час, пытаясь определить тонкую ошибку, вызванную изменением .startOf () исходной даты ... Спасибо за тяжелую работу, momentjs отлично поработал, показывая, как создать отличную библиотеку даты для JS, но я переключаюсь to date-fns из-за очень тонкой природы этого вида ошибок и потому, что после моего знакомства с некоторыми общими концепциями FP (в основном благодаря React, Redux и ELM) я начал ценить общие преимущества неизменяемости.

Как бы то ни было, lodash уже придерживается подхода, основанного на FP, с lodash / fp. Я бы посоветовал взглянуть на то, как был реализован lodash / fp, потому что они оборачивают свои существующие функции вместо того, чтобы полностью переписывать все. Ребята из Lodash тоже очень озабочены производительностью.

Я также согласен с @mull , настоящая проблема связана с API цепочки для меня, который IMO имеет некоторые серьезные недостатки дизайна не только в этом случае, но и в целом (например, jQuery). Было бы лучше, если бы даты изменения метода возвращали undefined (по крайней мере, это общее правило, которое я применяю к написанному мной коду)

Пока пространство имен moment.frozen находится в разработке, я бы рекомендовал - как предлагалось на предыдущем плакате - просто использовать date-fns .

Просто исправили еще одну ошибку из-за изменчивых моментов 🎉

По касательной, было бы здорово, если бы 3.0 можно было переместить в классы ES6:

let mom1 = new Moment();
let mom2 = Moment.parse('2019-03-01T14:55');
// etc

Такой шаг также может привести к обсуждению неизменности. Я бы сказал, что все методы должны быть неизменными, за одним исключением. Метод с названием .set('minute/hour/year/etc', 18) .

Я только начал использовать Moment и был ужасно потрясен тем, что эта библиотека не была полностью неизменной с самого начала. Я использую момент-неизменяемый, пока это не будет исправлено.

@alancnet момент, вероятно, никогда не будет изменен. Это слишком много изменений, и пользователи, которые научились принимать текущее поведение, получают достаточно сопротивления.

Посмотрите их новый проект: luxon
Это очень красиво, современно, неизменяемое (!) И должно работать лучше, чем момент-неизменяемый, который просто обертывает все вызовами .clone() .

Для тех, кто хочет перейти от momentjs к современному подходу, посетите https://github.com/you-dont-need/You-Dont-Need-Momentjs.

Очень удивлен, что это изменчиво!

Насколько Luxon станет заменой? Одна из причин, по которой я использую Moment.js, - это поддержка часовых поясов - это необходимо для моего проекта.

@alamothe На этот вопрос четко дан ответ на веб-сайте: https://moment.github.io/luxon/docs/manual/moment.html

Закрытие этого. Как указывали другие, используйте Luxon, если вам нужен в основном неизменяемый API. Спасибо.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги