Comments 31
Lo-dash имеет более высокую производительность, т.к. создан авторами сайта jsPerf.com
Аргумент…
Эти ребята знают, что делают. Можете сами проверить: lodash.com/benchmarks
Если я правильно понял, то Вы помещаете значения в ключи хэша, тем самым используя сильные стороны этой структуры.
Однако, это не будет работать со значениями, отличными от скаляров,. Но да, для чисел Ваш алгоритм работает хорошо.
Однако, это не будет работать со значениями, отличными от скаляров,. Но да, для чисел Ваш алгоритм работает хорошо.
Тоже сразу в глаза бросилось :)
Но ладно, Ваша взяла :)
Странно, что underscore в некоторых бенчмарках быстрее.
Но если полноценная замена, говорите, то можно попробовать. Во всяком случае, плюшки радуют.
Но если полноценная замена, говорите, то можно попробовать. Во всяком случае, плюшки радуют.
Ну часто underscore быстрее на пару процентов всего, это в пределах погрешности и обычно их алгоритмы в этих случаях совпадают.
Когда underscore быстрее значительно (а таких случаев немного), я это объясняю тем, что в среднем по всем браузерам эта реализация скорее всего лучше, но конкртно в этом — тормозит. По факту же, у себя в проекте такие медленные функции использовать не доводилось, так что для меня выбор в пользу Lo-Dash получился бескомпромиссным.
Когда underscore быстрее значительно (а таких случаев немного), я это объясняю тем, что в среднем по всем браузерам эта реализация скорее всего лучше, но конкртно в этом — тормозит. По факту же, у себя в проекте такие медленные функции использовать не доводилось, так что для меня выбор в пользу Lo-Dash получился бескомпромиссным.
Ну странный браузер (хром) и маловероятность функций (clone и contains) не отменяют факт. Мне просто интересно, почему они эти функции не сделали быстрее, ведь элементарно же было сделать хотя-бы не_медленнее. По факту эти функции действительно редкость.
Lo-Dash нормально копирует цепочку прототипов. Попробуйте в консоле хрома
и рассмотрите цепочку __proto__.
contains тоже переписана для поддержки не только массивов, правда не понимаю, зачем так усложнена в коде.
_(Object.create(Object.create({q:1,w:2,e:3}))).clone()
и рассмотрите цепочку __proto__.
contains тоже переписана для поддержки не только массивов, правда не понимаю, зачем так усложнена в коде.
Это приятно, да. Clone в underscore это обычный exntend пустого объекта.
У меня lodash.clone() и не клонирует этот объект :)
Если что, речь про node.js 0.8.15.
> var lodash = require('lodash');
undefined
> var a = Object.create(Object.create({q:1,w:2,e:3}));
undefined
> var b = lodash.clone(a);
undefined
> a === b
true
Если что, речь про node.js 0.8.15.
О как… И правда клонирование поломали, раньше работало:) Хотя пофик, нигде не использую.
Если так тема копирования волнует — более простые велосипеды использую — тык.
Работает и в ноде, и в браузерах, в т.ч. старых. Стандартные объекты, глубокое, сохранение цепочки прототипов, в отличии от большинства велосипедов — клонирование дескрипторов.
За скоростью не гонюсь, есть более быстрый варианты.
Если так тема копирования волнует — более простые велосипеды использую — тык.
Работает и в ноде, и в браузерах, в т.ч. старых. Стандартные объекты, глубокое, сохранение цепочки прототипов, в отличии от большинства велосипедов — клонирование дескрипторов.
За скоростью не гонюсь, есть более быстрый варианты.
Отлично. Я тут затеял глобальное исследование на эту тему.
Прогоню и Ваш клонер через тесты и бенчмарки .-)
Про дескрипторы не поскажете поподробнее, что требуется? Или, может, код теста подкините?
Прогоню и Ваш клонер через тесты и бенчмарки .-)
Про дескрипторы не поскажете поподробнее, что требуется? Или, может, код теста подкините?
С дескрипторами все просто — getOwnPropertyDescriptor для получения, defineProperty для установки. Дабы лишний раз геттеры не вызывать — для получения значения — value объекта getOwnPropertyDescriptor. Перед установкой delete затереть старые дескрипторы, перед слиянием value проверить наличие геттеров и сеттеров, хотя это скорее для слияния объектов. Скорость клонирования, само собой, падает в несколько(5-7 у меня) раз, так что фича не для включения по дефолту.
судя по моим тестам ( github.com/AlexeyKupershtokh/node-v8-clone/blob/master/test/shared.js ), у Вас в shallow-версии падают эти:
1) should clone number objects
2) should clone strings objects
3) should preserve Date instances custom properties
4) should preserve RegExp instances custom properties
5) should clone Functions
6) should preserve Functions custom properties
7) should clone inherited instances
В deep-версии добавляются еще такие:
15) should deeply clone Function custom properties
16) should deeply clone Date instances custom properties
17) should deeply clone RegExp instances custom properties
Их них важные наверное только 1, 2 и 7.
1) should clone number objects
2) should clone strings objects
3) should preserve Date instances custom properties
4) should preserve RegExp instances custom properties
5) should clone Functions
6) should preserve Functions custom properties
7) should clone inherited instances
В deep-версии добавляются еще такие:
15) should deeply clone Function custom properties
16) should deeply clone Date instances custom properties
17) should deeply clone RegExp instances custom properties
Их них важные наверное только 1, 2 и 7.
Гмм, у меня этот функционал покрыт тестами, унылыми, но полностью, все проходит, тесты прилагаются. Да и на продакшне без проблем. Полностью тест не прогнал, но в консоли 1,2,7 проходят без проблем. Похоже не так велосипед прикрутили:) Клонирование функций и custom properties стандартных конструкторов не предусмотрено, легко сделать — но замедлит код.
Прошу прощения. Неправильно вызывал ваш код, из-за чего возникла коллизия с другим модулем. Исправил, перезапустил.
Результаты теста.
zloirock Object.clone(value)
should clone primitives
✔ should clone null
✔ should clone undefined
✔ should clone boolean
✔ should clone numbers
✔ should clone strings
should clone builtin objects
✔ should clone number objects
1) should preserve number object custom properties
✔ should clone strings objects
2) should preserve string object custom properties
✔ should clone {} objects
✔ should clone Object.create(null) objects
✔ should clone inherited objects
✔ should clone arrays
3) should preserve array custom properties
✔ should clone Date instances
4) should preserve Date instances custom properties
✔ should clone RegExp instances
5) should preserve RegExp instances custom properties
✔ should clone Arguments
6) should preserve Arguments custom properties
7) should clone Functions
8) should preserve Functions custom properties
should clone custom objects
✔ should clone instances
✔ should clone inherited instances
zloirock Object.clone(value, true)
should clone primitives
✔ should clone null
✔ should clone undefined
✔ should clone boolean
✔ should clone numbers
✔ should clone strings
should clone builtin objects
✔ should clone number objects
9) should preserve number object custom properties
✔ should clone strings objects
10) should preserve string object custom properties
✔ should clone {} objects
✔ should clone Object.create(null) objects
✔ should clone inherited objects
✔ should clone arrays
11) should preserve array custom properties
✔ should clone Date instances
12) should preserve Date instances custom properties
✔ should clone RegExp instances
13) should preserve RegExp instances custom properties
✔ should clone Arguments
14) should preserve Arguments custom properties
15) should clone Functions
16) should preserve Functions custom properties
should clone custom objects
✔ should clone instances
✔ should clone inherited instances
should deeply clone objects
17) should deeply clone BooleanObject instances custom properties
18) should deeply clone NumberObject instances custom properties
19) should deeply clone StringObject instances custom properties
20) should deeply clone Function custom properties
21) should deeply clone Date instances custom properties
22) should deeply clone RegExp instances custom properties
✔ should deeply clone nested objects
✔ should deeply clone nested arrays
23) should deeply clone arrays with custom properties
should deeply clone circular objects
24) should clone nested objects with internal refs
25) should deeply clone circular arrays
26) should deeply clone circular objects
27) should deeply clone circular objects (lodash version)
К слову, node-v8-clone проходит все эти тесты. С одной оговоркой: там есть 2 pending теста касательно буферов и контекста замыканий. С ними пока не решил, что делать, и нужно ли/можно ли их клонировать :)
Вкусно, конечно, но только для ноды. Нужен был бы только сервер — и я бы модули на сях писал:) Ну а по тестам — про custom properties и клонирование функций — как писал — легко, но, средствами js, слишком дорого. Могу изменить за пару минут — будет проходить почти все. Но толку?)
А насчет circular — подумаю, может добавлю:)
А насчет circular — подумаю, может добавлю:)
или, чтоп совсем уж понятно было, сравните в Lo-Dash и Underscore
function fn(){};
_.clone(new fn) instanceof fn;
github.com/AlexeyKupershtokh/node-v8-clone/wiki/Comparison
касательно качества клонирования :)
касательно качества клонирования :)
с backbone.js совместим? в смысле можно использовать как замену андерскор для бэкбон проектов?
У Lo-Dash есть 2 сборки специально для Вас:
Сборка с повышенной совместимостью
Также есть минималистичная версия именно для Backbone
Сборка с повышенной совместимостью
lodash underscore
, которая может пригодиться, если не получится завести со стандартной.Также есть минималистичная версия именно для Backbone
lodash backbone
.Если в underscore ничего не поменялось, то _.difference в lodash на больших объёмах (сотни тысяч) работает в овер 650 раз быстрее :)
Вот еще один бенчмарк:
habrastorage.org/storage2/d69/189/631/d6918963117e2bd4d41a1e6ddce1c7c4.gif
habrastorage.org/storage2/d69/189/631/d6918963117e2bd4d41a1e6ddce1c7c4.gif
Зато я нашел багу в _.clone, из-за чего он работает в 100 раз медленнее на огромных объектах (суммарно 18000 объектов, 4 уровня вложенности) :)
Sign up to leave a comment.
Lo-Dash