{"action":"created","issue":{"url":"https://api.github.com/repos/lodash/lodash/issues/1496","labels_url":"https://api.github.com/repos/lodash/lodash/issues/1496/labels{/name}","comments_url":"https://api.github.com/repos/lodash/lodash/issues/1496/comments","events_url":"https://api.github.com/repos/lodash/lodash/issues/1496/events","html_url":"https://github.com/lodash/lodash/issues/1496","id":108935753,"number":1496,"title":"lodash deepclone scales poorly","user":{"login":"iarna","id":983798,"avatar_url":"https://avatars.githubusercontent.com/u/983798?v=3","gravatar_id":"","url":"https://api.github.com/users/iarna","html_url":"https://github.com/iarna","followers_url":"https://api.github.com/users/iarna/followers","following_url":"https://api.github.com/users/iarna/following{/other_user}","gists_url":"https://api.github.com/users/iarna/gists{/gist_id}","starred_url":"https://api.github.com/users/iarna/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iarna/subscriptions","organizations_url":"https://api.github.com/users/iarna/orgs","repos_url":"https://api.github.com/users/iarna/repos","events_url":"https://api.github.com/users/iarna/events{/privacy}","received_events_url":"https://api.github.com/users/iarna/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/lodash/lodash/labels/enhancement","name":"enhancement","color":"84b6eb"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-09-29T18:54:06Z","updated_at":"2015-09-29T20:05:14Z","closed_at":null,"body":"I encountered this in particular in cloning huge cross linked tree structures for npm.\r\n\r\nPer discussion on Twitter, this is due to the circular dependency check:\r\n```\r\n * @param {Array} [stackA=[]] Tracks traversed source objects.\r\n * @param {Array} [stackB=[]] Associates clones with source counterparts.\r\n```\r\n```\r\n  var length = stackA.length;\r\n  while (length--) {\r\n    if (stackA[length] == value) {\r\n      return stackB[length];\r\n    }\r\n  }\r\n```\r\n\r\nNow, if lodash could count on access to Maps or WeakMaps then this could be easily worked with of course.  This led me to investigating how es6 map shims work– many of them work like lodash, doing a linear scan of a keys array, but core-js does not:\r\n\r\nhttps://github.com/zloirock/core-js\r\n\r\nIt's implementation is here:\r\n\r\nhttps://github.com/zloirock/core-js/blob/master/modules/es6.map.js\r\n\r\nWhich in turn has the bulk of its implementation here:\r\n\r\nhttps://github.com/zloirock/core-js/blob/master/modules/%24.collection-strong.js\r\n\r\nIf you dig into that, you can see that ultimately they add a non-enumerable element named `ID` with a unique id they generate and use that as the key for their Map objects.\r\n\r\nUh... I'm not exactly sure what I'm suggesting here. The current behavior works fine for small objects but goes very very bad with large ones. At the same time, mutating the original object is super ugly. =/ I kind of don't like either option.\r\n\r\nMy colleague @zkat suggested maybe having deep-clone take an optional additional argument that's a function that, given an object returns a unique identifier for it.  If this was passed in then deep-clone could use this to compute a key to be used in a fast property lookup instead of scanning a list– with the list scan as a fallback if such a function doesn't exist. The end user could then choose to either mutate their objects or use knowledge of how their data structures to select an already existing unique property…\r\n "},"comment":{"url":"https://api.github.com/repos/lodash/lodash/issues/comments/144175136","html_url":"https://github.com/lodash/lodash/issues/1496#issuecomment-144175136","issue_url":"https://api.github.com/repos/lodash/lodash/issues/1496","id":144175136,"user":{"login":"jdalton","id":4303,"avatar_url":"https://avatars.githubusercontent.com/u/4303?v=3","gravatar_id":"","url":"https://api.github.com/users/jdalton","html_url":"https://github.com/jdalton","followers_url":"https://api.github.com/users/jdalton/followers","following_url":"https://api.github.com/users/jdalton/following{/other_user}","gists_url":"https://api.github.com/users/jdalton/gists{/gist_id}","starred_url":"https://api.github.com/users/jdalton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jdalton/subscriptions","organizations_url":"https://api.github.com/users/jdalton/orgs","repos_url":"https://api.github.com/users/jdalton/repos","events_url":"https://api.github.com/users/jdalton/events{/privacy}","received_events_url":"https://api.github.com/users/jdalton/received_events","type":"User","site_admin":false},"created_at":"2015-09-29T20:05:14Z","updated_at":"2015-09-29T20:05:14Z","body":"@iarna Out of curiosity (and to help with future heuristics) do you happen to know how many circular reference checks it was performing?"}}