Add _.setWith.

This commit is contained in:
John-David Dalton
2015-07-23 08:16:31 -07:00
parent 7e42892e6a
commit 4520e0710d
2 changed files with 74 additions and 36 deletions

108
lodash.js
View File

@@ -859,9 +859,9 @@
* `omit`, `omitBy`, `once`, `pairs`, `partial`, `partialRight`, `partition`, * `omit`, `omitBy`, `once`, `pairs`, `partial`, `partialRight`, `partition`,
* `pick`, `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAt`, * `pick`, `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAt`,
* `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`, `reverse`, * `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`, `reverse`,
* `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByOrder`, `splice`, * `set`, `setWith`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByOrder`,
* `spread`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, * `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`,
* `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, `transform`, * `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, `transform`,
* `union`, `uniq`, `uniqBy`, `unshift`, `unzip`, `unzipWith`, `values`, * `union`, `uniq`, `uniqBy`, `unshift`, `unzip`, `unzipWith`, `values`,
* `valuesIn`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith` * `valuesIn`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith`
* *
@@ -1932,21 +1932,19 @@
} }
/** /**
* The base implementation of `get` without support for string paths and default values. * The base implementation of `_.get` without support for default values or
* nullish `object` values.
* *
* @private * @private
* @param {Object} object The object to query. * @param {Object} object The object to query.
* @param {Array} path The path of the property to get. * @param {Array|string} path The path of the property to get.
* @param {string} [pathKey] The key representation of path. * @param {string} [pathKey] The key representation of path.
* @returns {*} Returns the resolved value. * @returns {*} Returns the resolved value.
*/ */
function baseGet(object, path, pathKey) { function baseGet(object, path, pathKey) {
if (object == null) { pathKey = pathKey == null ? (path + '') : pathKey;
return; path = isKey(pathKey, object) ? [pathKey] : toPath(path);
}
if (pathKey !== undefined && pathKey in Object(object)) {
path = [pathKey];
}
var index = 0, var index = 0,
length = path.length; length = path.length;
@@ -2473,6 +2471,44 @@
return accumulator; return accumulator;
} }
/**
* The base implementation of `_.set` without support for nullish `object` values.
*
* @private
* @param {Object} object The object to query.
* @param {Array|string} path The path of the property to get.
* @param {Function} [customizer] The function to customize cloning.
* @returns {*} Returns the resolved value.
*/
function baseSet(object, path, value, customizer) {
path = isKey(path, object) ? [path + ''] : toPath(path);
var index = -1,
length = path.length,
lastIndex = length - 1,
nested = object;
while (nested != null && ++index < length) {
var key = path[index];
if (isObject(nested)) {
if (index == lastIndex) {
nested[key] = value;
}
else {
var other = nested[key],
result = customizer ? customizer(other, key, nested) : undefined;
if (result === undefined) {
result = other == null ? (isIndex(path[index + 1]) ? [] : {}) : other;
}
nested[key] = result;
}
}
nested = nested[key];
}
return object;
}
/** /**
* The base implementation of `setData` without support for hot loop detection. * The base implementation of `setData` without support for hot loop detection.
* *
@@ -8880,7 +8916,7 @@
* // => 'default' * // => 'default'
*/ */
function get(object, path, defaultValue) { function get(object, path, defaultValue) {
var result = object == null ? undefined : baseGet(object, toPath(path), (path + '')); var result = object == null ? undefined : baseGet(object, path);
return result === undefined ? defaultValue : result; return result === undefined ? defaultValue : result;
} }
@@ -9380,29 +9416,30 @@
* // => 5 * // => 5
*/ */
function set(object, path, value) { function set(object, path, value) {
if (object == null) { return object == null ? object : baseSet(object, path, value);
return object; }
}
var pathKey = (path + '');
path = (object[pathKey] != null || isKey(path, object)) ? [pathKey] : toPath(path);
var index = -1, /**
length = path.length, * This method is like `_.set` except that it accepts `customizer` which
lastIndex = length - 1, * is invoked to produce the namespace objects of `path`. The `customizer`
nested = object; * is invoked with three arguments: (nsValue, key, nsObject).
*
while (nested != null && ++index < length) { * @static
var key = path[index]; * @memberOf _
if (isObject(nested)) { * @category Object
if (index == lastIndex) { * @param {Object} object The object to augment.
nested[key] = value; * @param {Array|string} path The path of the property to set.
} else if (nested[key] == null) { * @param {*} value The value to set.
nested[key] = isIndex(path[index + 1]) ? [] : {}; * @param {Function} [customizer] The function to customize assigned values.
} * @returns {Object} Returns `object`.
} * @example
nested = nested[key]; *
} * _.setWith({}, '[0][1][2]', 3, Object);
return object; * // => { '0': { '1': { '2': 3 } } }
*/
function setWith(object, path, value, customizer) {
customizer = typeof customizer == 'function' ? customizer : undefined;
return object == null ? object : baseSet(object, path, value, customizer);
} }
/** /**
@@ -10869,7 +10906,7 @@
*/ */
function propertyOf(object) { function propertyOf(object) {
return function(path) { return function(path) {
return baseGet(object, toPath(path), (path + '')); return object == null ? undefined : baseGet(object, path);
}; };
} }
@@ -11353,6 +11390,7 @@
lodash.rest = rest; lodash.rest = rest;
lodash.restParam = restParam; lodash.restParam = restParam;
lodash.set = set; lodash.set = set;
lodash.setWith = setWith;
lodash.shuffle = shuffle; lodash.shuffle = shuffle;
lodash.slice = slice; lodash.slice = slice;
lodash.sortBy = sortBy; lodash.sortBy = sortBy;

View File

@@ -17178,7 +17178,7 @@
var acceptFalsey = _.difference(allMethods, rejectFalsey); var acceptFalsey = _.difference(allMethods, rejectFalsey);
test('should accept falsey arguments', 221, function() { test('should accept falsey arguments', 222, function() {
var emptyArrays = _.map(falsey, _.constant([])); var emptyArrays = _.map(falsey, _.constant([]));
_.each(acceptFalsey, function(methodName) { _.each(acceptFalsey, function(methodName) {