Upgrading Lodash from 3.x to 4.x
There are many breaking changes from version 3.x to 4.x; all changes are detailed in the Lodash changelog. There is also a list of deprecated functions, with a regex you can use to detect usages in your code.
However, since it is not an exhaustive list, I will list the changes I encountered when performing my own migration, to help anyone undergoing the same process.
Direct renames
This section includes functions in which only the name changed, i.e. the arguments and return value are the same.
3.x | 4.x |
---|---|
contains | includes |
first | head |
rest | tail |
invoke | invokeMap |
padLeft | padStart |
padRight | padEnd |
Direct renames if not using thisArg
This section includes functions in which the only change is dropping "thisArg". If you are not using it, you can just rename. If you are using thisArg in 3.x, it can be dropped if you are using iteratee to access the collection elements. If you want to bind some other object, you can use bind.
3.x | 4.x |
---|---|
any | some |
indexBy | keyBy |
all | every |
Different arguments
3.x | 4.x | Changes |
---|---|---|
extend | assignIn | If you were using the customizer argument, use _.map beforehand to perform the conversion. If you were using thisArg, drop it, or use bind |
pluck | map | Plucking can be done with _.map, by passing a single property name as a string as the 2nd argument (property shorthand), or an array of strings to pluck more than one. |
sum | sumBy | If you are just adding numbers in an array, it's okay to leave sum as it is. However, if you are adding properties in objects, you need to use sumBy instead (you can use the property shorthand instead of a function; see the examples in the docs). |
omit | omit | Change the second argument to an array of string instead of a single string, if using the property shorthand (like pluck). |
uniq | uniqBy | Same change as sum and sumBy (property shorthand is valid, try it in REPL in the 4.x docs). |
pick | pick | In the new version, the 2nd argument cannot be a predicate function, just a string array with property names to pick. |
min | minBy | Same change as sum and sumBy. |
max | maxBy | Same change as sum and sumBy. |
Special case: _.zipObject
This function is tricky, because it is apparently the same; however, the way arguments are interpreted has changed. In 3.x, the first argument can be an array in which each element is a 2-item array representing a key-value pair. However, in 4.x, the first argument is an array with the keys, and the second argument is an array with the values. So if you see _.zipObject receiving a single argument, you're in trouble. Since converting arguments to the new convention in each call is a hassle, and quite error prone, I implemented my own zipObject function:
/**
* Converts [[key0, value0], [key1, value1], ..., [keyN, valueN]]
* to {key0: value0, key1: value1, ..., keyN: valueN}
* @param keyValuePairs Array of key-value pairs, where each element is an array of
* two elements [keyi, valuei]
* @returns An object whose properties are keyi: valuei
*/
Utils.zipObject = function(keyValuePairs) {
var zippedObject = {};
for(var i=0; i<keyValuePairs.length; i++) {
if(keyValuePairs[i] && keyValuePairs[i].length === 2) {
zippedObject[keyValuePairs[i][0]] = keyValuePairs[i][1];
}
};
return zippedObject;
}
Conclusion
As in most cases involving breaking changes, it is very helpful to have a test harness to detect as many errors introduced by the changes as possible. In my particular case, I had Mocha + Chai + Sinon tests in place. To debug them when they broke, VS Code was very helpful. So, if you don't have a test harness in place, I would recommend implementing one which covers all Lodash usages before tackling this migration.
About Lodash usage today, some people advocate removing the dependency, since lots of Lodash functions have been made obsolete by recent additions to the ECMA standard, or Modern JS as some call it. It is certainly a point to consider, specially if you are not using complex, specific Lodash functions which are not yet in the standard. Because each Lodash function is available as a separate npm package, you can replace as many usages as possible with Modern JS, and keep the rest as separate packages, avoiding referencing all of Lodash and thus reducing your app's footprint.
Comments
Post a Comment