Add _.propertyDeep and _.propertyDeepOf.

This commit is contained in:
Joshua Piccari
2015-03-27 18:01:27 -07:00
committed by jdalton
parent 515cfd48d8
commit 3d0beb1a2e
2 changed files with 172 additions and 1 deletions

View File

@@ -2598,6 +2598,31 @@
};
}
/**
* The base implementation of `_.propertyDeep` which does not coerce `keys` to strings.
*
* @private
* @param {string[]} keys Keys that specify the property to get.
* @returns {Function} Returns the new function.
*/
function basePropertyDeep(keys) {
return function(object) {
if (object == null) {
return undefined;
}
var index = -1,
length = keys.length;
while (++index < length) {
object = object[keys[index]];
if (object == null) {
return undefined;
}
}
return object;
};
}
/**
* The base implementation of `_.pullAt` without support for individual
* index arguments and capturing the removed elements.
@@ -11243,6 +11268,33 @@
return baseProperty(key + '');
}
/**
* This function is like `_.property` except it takes a `keys` array to get nested property.
* @static
* @memberOf _
* @category Utility
* @param {string[]} keys Keys that specify the property to get.
* @returns {Function} Returns the new function.
* @example
*
* var users = [
* { 'user': { 'name': 'fred' } },
* { 'user': { 'name': 'barney', 'age': 36 } }
* ];
*
* var getName = _.propertyDeep(['user', 'name']);
* var getAge = _.propertyDeep(['user', 'age']);
*
* _.map(users, getName);
* // => ['fred', 'barney']
*
* _.map(users, getAge);
* // => [undefined, 36]
*/
function propertyDeep(keys) {
return basePropertyDeep(arrayMap(keys || [], baseToString));
}
/**
* The opposite of `_.property`; this method creates a function which returns
* the property value of a given key on `object`.
@@ -11268,6 +11320,36 @@
};
}
/**
* The opposite of `_.propertyDeep`; this method creates a function which returns
* the property value of a given key path on `object`.
*
* @static
* @memberOf _
* @category Utility
* @param {Object} object The object to inspect.
* @returns {Function} Returns the new function.
* @example
*
* var users = [
* { user: 'fredrick', nickname: 'fred' },
* { user: 'bernard', nickname: 'barney' }
* ];
*
* var propertyOfUsers = _.propertyDeepOf(users);
*
* propertyOfUsers([0, 'nickname']);
* // => 'fred'
*
* propertyOfUsers([1, 'name']);
* // => 'bernard'
*/
function propertyDeepOf(object) {
return function(keyPath) {
return resultDeep(object, keyPath);
};
}
/**
* Creates an array of numbers (positive and/or negative) progressing from
* `start` up to, but not including, `end`. If `end` is not specified it is
@@ -11651,7 +11733,9 @@
lodash.pick = pick;
lodash.pluck = pluck;
lodash.property = property;
lodash.propertyDeep = propertyDeep;
lodash.propertyOf = propertyOf;
lodash.propertyDeepOf = propertyDeepOf;
lodash.pull = pull;
lodash.pullAt = pullAt;
lodash.range = range;

View File

@@ -11588,6 +11588,58 @@
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.propertyDeep');
(function() {
test('should create a function that plucks a property value of a given object', 3, function() {
var object = { 'a': [1, 2], 'b': 3 },
prop = _.propertyDeep(['a', 1]);
strictEqual(prop.length, 1);
strictEqual(prop(object), 2);
prop = _.propertyDeep(['b']);
strictEqual(prop(object), 3);
});
test('should work with non-string `prop` arguments', 1, function() {
var prop = _.propertyDeep([1]);
strictEqual(prop([1, 2, 3]), 2);
});
test('should return a function even for falsey values', 1, function() {
var pass = true;
_.each(falsey, function(keys) {
pass = typeof _.propertyDeep(keys) == 'function'
});
ok(pass);
});
test('should pluck inherited property values', 1, function() {
function Foo() { this.a = 1; }
Foo.prototype.b = 2;
var prop = _.propertyDeep(['b']);
strictEqual(prop(new Foo), 2);
});
test('should work when `object` is nullish', 1, function() {
var values = [, null, undefined],
expected = _.map(values, _.constant(undefined));
var actual = _.map(values, function(value, index) {
var prop = _.propertyDeep(['a']);
return index ? prop(value) : prop();
});
deepEqual(actual, expected);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.propertyOf');
(function() {
@@ -11623,6 +11675,41 @@
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.propertyDeepOf');
(function() {
test('should create a function that plucks a property value of a given key', 3, function() {
var object = { 'a': 1, 'b': 2 },
propOf = _.propertyDeepOf(object);
strictEqual(propOf.length, 1);
strictEqual(propOf(['a']), 1);
strictEqual(propOf(['b']), 2);
});
test('should pluck inherited property values', 1, function() {
function Foo() { this.a = 1; }
Foo.prototype.b = 2;
var propOf = _.propertyDeepOf(new Foo);
strictEqual(propOf(['b']), 2);
});
test('should work when `object` is nullish', 1, function() {
var values = [, null, undefined],
expected = _.map(values, _.constant(undefined));
var actual = _.map(values, function(value, index) {
var propOf = index ? _.propertyDeepOf(value) : _.propertyDeepOf();
return propOf(['a']);
});
deepEqual(actual, expected);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.pull');
(function() {
@@ -16581,7 +16668,7 @@
var acceptFalsey = _.difference(allMethods, rejectFalsey);
test('should accept falsey arguments', 214, function() {
test('should accept falsey arguments', 216, function() {
var emptyArrays = _.map(falsey, _.constant([])),
isExposed = '_' in root,
oldDash = root._;