Skip to content

Instantly share code, notes, and snippets.

@alvaropinot
Last active June 21, 2016 09:59
Show Gist options
  • Save alvaropinot/39fdc70739646114f5708f5aafb96222 to your computer and use it in GitHub Desktop.
Save alvaropinot/39fdc70739646114f5708f5aafb96222 to your computer and use it in GitHub Desktop.
get.js
function _get(property, defaultValue) {
var path = property.split(/[\.\["'\]]+/);
return function(obj) {
return typeof obj === 'object' ? path.reduce(function (acc, key) {
var value = acc && acc[key];
// should allow null and falsy values.
return (value || (value !== undefined)) ?
value :
defaultValue;
}, obj) :
obj;
}
}
test('should return a level one property', function () {
var obj = {
foo: 'foo'
};
var actual = _get('foo')(obj),
expected = 'foo';
equal(actual, expected);
});
test('should return a level two property', function () {
var obj = {
foo: {
bar: 'bar'
}
};
var actual = _get('foo.bar')(obj),
expected = 'bar';
equal(actual, expected);
});
test('called with no value', function () {
var actual = _get('foo.bar')(),
expected = undefined;
equal(actual, expected, 'should return undefined');
});
test('called with a primitive value instead of an object', function () {
var actual = _get('foo.bar')(2),
expected = 2;
equal(actual, expected, 'should return the value');
});
test('should allow a default value when a property its not defined', function () {
var obj = {
foo: {
bar: 'bar'
}
};
var actual = _get('foo.biz', 5)(obj),
expected = 5;
equal(actual, expected, 'should return the default value');
actual = _get('bar', 5)(obj);
expected = 5;
equal(actual, expected, 'should return the default value');
});
test('should work for keys with `null` values', function () {
var obj = {
foo: {
bar: null
}
};
var actual = _get('foo.bar', 5)(obj),
expected = null;
equal(actual, expected, 'should return null');
});
test('should work for keys with `false` values', function () {
var obj = {
foo: {
bar: false
}
};
var actual = _get('foo.bar', 5)(obj),
expected = false;
equal(actual, expected, 'should return false');
});
test('should work for keys with `0` values', function () {
var obj = {
foo: {
bar: 0
}
};
var actual = _get('foo.bar', 5)(obj),
expected = 0;
equal(actual, expected, 'should return 0');
});
test('should return default value for undefined keys', function () {
var obj = {
foo: {
bar: undefined
}
};
var actual = _get('foo.bar', 5)(obj),
expected = 5;
equal(actual, expected, 'should return the default value');
});
test('should return default value for undefined keys', function () {
var obj = {
foo: {
bar: {
biz: 'biz'
}
}
};
var actual = _get('foo.bar.biz', 5)(obj),
expected = 'biz';
equal(actual, expected);
});
// TODO: move to array tests module and clean those objs.
test('should work with deep arrays', function () {
var obj = {
foo: {
arr: [
{},
{
subarr: [
{},
{
name:'rita'
}
]
}
]
}
};
var actual = _get('foo.arr[1].subarr[1].name')(obj),
expected = 'rita';
equal(actual, expected);
});
test('should work with deep arrays and undenined properties', function () {
var obj = {
foo: {
arr: [
{},
{
subarr: [
{},
{
name:'rita'
}
]
}
]
}
};
var actual = _get('foo.arr[2].subarr[5].name')(obj),
expected = undefined;
equal(actual, expected);
});
test('should work with deep arrays and return defaultValue', function () {
var obj = {
foo: {
arr: [
{},
{
subarr: [
{},
{
name:'rita'
}
]
}
]
}
};
var actual = _get('foo.arr[2].subarr[5].name', 2)(obj),
expected = 2;
equal(actual, expected);
});
@sergueyarellano
Copy link

another variant if you want a default value only if you pass it, and the current value is falsy:

function _get(parent, nested, defaultValue) {
    var argsLength = [].slice.call(arguments).length; // get arguments length
    var value = typeof nested === 'string' ?
        (typeof parent === 'object' &&
        nested
            .split(/[\.\["'\]]+/)
            .reduce(function(acc, current) {
                return /^$/.test(current) ? acc : acc && acc[current]; // checking for empty strings
            }, parent)) :
        parent;
    return argsLength === 3 ? value || defaultValue : value; // if defaultValue is passed, then return default only if value is falsy
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment