Add _.get and _.set.

This commit is contained in:
jdalton
2015-03-29 20:59:48 -07:00
parent 18313f2e90
commit 2edcc89303
2 changed files with 128 additions and 37 deletions

View File

@@ -2254,6 +2254,26 @@
return result; return result;
} }
/**
* The base implementation of `get` without support for string paths
* and default values.
*
* @private
* @param {Object} object The object to query.
* @param {Array} path The path of the property to get.
* @returns {*} Returns the resolved value.
*/
function baseGet(object, path) {
var result,
index = -1,
length = path.length;
while (object != null && ++index < length) {
result = object = object[path[index]];
}
return result;
}
/** /**
* The base implementation of `_.isEqual` without support for `this` binding * The base implementation of `_.isEqual` without support for `this` binding
* `customizer` functions. * `customizer` functions.
@@ -2493,7 +2513,7 @@
var key = pathKey; var key = pathKey;
object = toObject(object); object = toObject(object);
if (!(key in object)) { if (!(key in object)) {
object = getPath(object, baseSlice(path, 0, -1)); object = baseGet(object, baseSlice(path, 0, -1));
if (object == null) { if (object == null) {
return false; return false;
} }
@@ -2619,7 +2639,7 @@
* A specialized version of `baseProperty` which supports deep paths. * A specialized version of `baseProperty` which supports deep paths.
* *
* @private * @private
* @param {string} path The path of the property to get. * @param {Array|string} path The path of the property to get.
* @returns {Function} Returns the new function. * @returns {Function} Returns the new function.
*/ */
function basePropertyDeep(path) { function basePropertyDeep(path) {
@@ -2631,7 +2651,7 @@
} }
return pathKey in toObject(object) return pathKey in toObject(object)
? object[pathKey] ? object[pathKey]
: getPath(object, path); : baseGet(object, path);
}; };
} }
@@ -4083,16 +4103,6 @@
return collection ? result(collection, target, fromIndex) : result; return collection ? result(collection, target, fromIndex) : result;
} }
function getPath(object, path) {
var index = -1,
length = path.length;
while (object != null && ++index < length) {
object = object[path[index]];
}
return object;
}
/** /**
* Gets the view, applying any `transforms` to the `start` and `end` positions. * Gets the view, applying any `transforms` to the `start` and `end` positions.
* *
@@ -4560,8 +4570,8 @@
return value; return value;
} }
var result = []; var result = [];
(value + '').replace(rePropName, function(match, key, number, quote, string) { (value + '').replace(rePropName, function(match, number, quote, string) {
result.push(key || number || string); result.push(typeof string == 'string' ? string : (number || match));
}); });
return result; return result;
} }
@@ -6861,13 +6871,13 @@
}, function() { return [[], []]; }); }, function() { return [[], []]; });
/** /**
* Gets the value of `path` from all elements in `collection`. * Gets the property value of `path` from all elements in `collection`.
* *
* @static * @static
* @memberOf _ * @memberOf _
* @category Collection * @category Collection
* @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Object|string} collection The collection to iterate over.
* @param {string} path The path of the property to pluck. * @param {Array|string} path The path of the property to pluck.
* @returns {Array} Returns the property values. * @returns {Array} Returns the property values.
* @example * @example
* *
@@ -9440,6 +9450,40 @@
return baseFunctions(object, keysIn(object)); return baseFunctions(object, keysIn(object));
} }
/**
* Gets the property value of `path` on `object`. If the resolved value is
* `undefined` the `defaultValue` is used in its place.
*
* @static
* @memberOf _
* @category Object
* @param {Object} object The object to query.
* @param {Array|string} path The path of the property to get.
* @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
* @returns {*} Returns the resolved value.
* @example
*
* var object = { 'a': [{ 'b': { 'c': 3 } }] };
*
* _.get(object, 'a[0].b.c');
* // => 3
*
* _.get(object, ['a', '0', 'b', 'c']);
* // => 3
*
* _.get(object, 'a.b.c', 'default');
* // => 'default'
*/
function get(object, path, defaultValue) {
var result;
if (object != null) {
result = (isKey(path) || (path in toObject(object)))
? object[path]
: baseGet(object, toPath(path));
}
return typeof result == 'undefined' ? defaultValue : result;
}
/** /**
* Checks if `path` is a direct property. * Checks if `path` is a direct property.
* *
@@ -9447,7 +9491,7 @@
* @memberOf _ * @memberOf _
* @category Object * @category Object
* @param {Object} object The object to inspect. * @param {Object} object The object to inspect.
* @param {string} path The path to check. * @param {Array|string} path The path to check.
* @returns {boolean} Returns `true` if `path` is a direct property, else `false`. * @returns {boolean} Returns `true` if `path` is a direct property, else `false`.
* @example * @example
* *
@@ -9460,7 +9504,7 @@
var result = object != null && hasOwnProperty.call(object, path); var result = object != null && hasOwnProperty.call(object, path);
if (!result && !isKey(path)) { if (!result && !isKey(path)) {
path = toPath(path); path = toPath(path);
object = getPath(object, baseSlice(path, 0, -1)); object = baseGet(object, baseSlice(path, 0, -1));
result = object != null && hasOwnProperty.call(object, last(path)); result = object != null && hasOwnProperty.call(object, last(path));
} }
return result; return result;
@@ -9841,18 +9885,16 @@
}); });
/** /**
* Resolves the value of property `path` on `object`. If the value of `path` * This method is like `_.get` except that if the resolved value is a function
* is a function it is invoked with the `this` binding of `object` and its * it is invoked with the `this` binding of its parent object and its result
* result is returned, else the property value is returned. If the property * is returned.
* value is `undefined` the `defaultValue` is used in its place.
* *
* @static * @static
* @memberOf _ * @memberOf _
* @category Object * @category Object
* @param {Object} object The object to query. * @param {Object} object The object to query.
* @param {string} path The path of the property to resolve. * @param {Array|string} path The path of the property to resolve.
* @param {*} [defaultValue] The value returned if the property value * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
* resolves to `undefined`.
* @returns {*} Returns the resolved value. * @returns {*} Returns the resolved value.
* @example * @example
* *
@@ -9871,16 +9913,62 @@
* // => 'busy' * // => 'busy'
*/ */
function result(object, path, defaultValue) { function result(object, path, defaultValue) {
if (object != null && !isKey(path) && !(path in toObject(object))) { if (object != null && !(isKey(path) || (path in toObject(object)))) {
path = toPath(path); path = toPath(path);
object = getPath(object, baseSlice(path, 0, -1)); object = baseGet(object, baseSlice(path, 0, -1));
path = last(path); path = last(path);
} }
var value = object == null ? undefined : object[path]; var result = object == null ? undefined : object[path];
if (typeof value == 'undefined') { if (typeof result == 'undefined') {
value = defaultValue; result = defaultValue;
} }
return isFunction(value) ? value.call(object) : value; return isFunction(result) ? result.call(object) : result;
}
/**
* Sets the property value of `path` on `object`. If a portion of `path`
* does not exist it is created.
*
* @static
* @memberOf _
* @category Object
* @param {Object} object The object to augment.
* @param {Array|string} path The path of the property to set.
* @param {*} value The value to set.
* @returns {Object} Returns `object`.
* @example
*
* var object = { 'a': { 'b': { 'c': 3 } } };
*
* _.set(object, 'a.b.c', 4);
* console.log(object.a.b.c);
* // => 4
*
* _.set(object, 'x[0].y.z', 5);
* console.log(object.x[0].y.z);
* // => 5
*/
function set(object, path, value) {
if (object == null) {
return object;
}
path = toPath(path);
var index = -1,
length = path.length,
endIndex = length - 1,
nested = object;
while (++index < length) {
var key = path[index];
if (index == endIndex) {
nested[key] = value;
} else if (nested[key] == null) {
nested[key] = isIndex(path[index + 1]) ? [] : {};
}
nested = nested[key];
}
return object;
} }
/** /**
@@ -11120,7 +11208,7 @@
* @static * @static
* @memberOf _ * @memberOf _
* @category Utility * @category Utility
* @param {string} path The path of the property to get. * @param {Array|string} path The path of the property to get.
* @param {*} value The value to compare. * @param {*} value The value to compare.
* @returns {Function} Returns the new function. * @returns {Function} Returns the new function.
* @example * @example
@@ -11265,12 +11353,13 @@
} }
/** /**
* Creates a function which returns the property value of `path` on a given object. * Creates a function which returns the property value of `path` on a
* given object.
* *
* @static * @static
* @memberOf _ * @memberOf _
* @category Utility * @category Utility
* @param {string} path The path of the property to get. * @param {Array|string} path The path of the property to get.
* @returns {Function} Returns the new function. * @returns {Function} Returns the new function.
* @example * @example
* *
@@ -11317,7 +11406,7 @@
return function(path) { return function(path) {
return (isKey(path) || (path in toObject(object))) return (isKey(path) || (path in toObject(object)))
? object[path] ? object[path]
: getPath(object, toPath(path)); : baseGet(object, toPath(path));
}; };
} }
@@ -11713,6 +11802,7 @@
lodash.remove = remove; lodash.remove = remove;
lodash.rest = rest; lodash.rest = rest;
lodash.restParam = restParam; lodash.restParam = restParam;
lodash.set = set;
lodash.shuffle = shuffle; lodash.shuffle = shuffle;
lodash.slice = slice; lodash.slice = slice;
lodash.sortBy = sortBy; lodash.sortBy = sortBy;
@@ -11781,6 +11871,7 @@
lodash.findLastKey = findLastKey; lodash.findLastKey = findLastKey;
lodash.findWhere = findWhere; lodash.findWhere = findWhere;
lodash.first = first; lodash.first = first;
lodash.get = get;
lodash.has = has; lodash.has = has;
lodash.identity = identity; lodash.identity = identity;
lodash.includes = includes; lodash.includes = includes;

View File

@@ -16543,7 +16543,7 @@
var acceptFalsey = _.difference(allMethods, rejectFalsey); var acceptFalsey = _.difference(allMethods, rejectFalsey);
test('should accept falsey arguments', 213, function() { test('should accept falsey arguments', 215, function() {
var emptyArrays = _.map(falsey, _.constant([])), var emptyArrays = _.map(falsey, _.constant([])),
isExposed = '_' in root, isExposed = '_' in root,
oldDash = root._; oldDash = root._;