在ES6 (ES2015/JavaScript.next/Harmony)中是否有一个空安全的属性访问(空传播/存在)操作符?比如CoffeeScript ?还是计划在ES7中?
var aThing = getSomething()
...
aThing = possiblyNull?.thing
大致如下:
if (possiblyNull != null) aThing = possiblyNull.thing
理想情况下,解决方案不应该分配(甚至未定义)一个东西,如果posblynull是空的
// The code for the regex isn't great,
// but it suffices for most use cases.
/**
* Gets the value at `path` of `object`.
* If the resolved value is `undefined`,
* or the property does not exist (set param has: true),
* the `defaultValue` is returned in its place.
*
* @param {Object} object The object to query.
* @param {Array|string} path The path of the property to get.
* @param {*} [def] The value returned for `undefined` resolved values.
* @param {boolean} [has] Return property instead of default value if key exists.
* @returns {*} Returns the resolved value.
* @example
*
* var object = { 'a': [{ 'b': { 'c': 3 } }], b: {'c-[d.e]': 1}, c: { d: undefined, e: 0 } };
*
* dotGet(object, 'a[0].b.c');
* // => 3
*
* dotGet(object, ['a', '0', 'b', 'c']);
* // => 3
*
* dotGet(object, ['b', 'c-[d.e]']);
* // => 1
*
* dotGet(object, 'c.d', 'default value');
* // => 'default value'
*
* dotGet(object, 'c.d', 'default value', true);
* // => undefined
*
* dotGet(object, 'c.d.e', 'default value');
* // => 'default value'
*
* dotGet(object, 'c.d.e', 'default value', true);
* // => 'default value'
*
* dotGet(object, 'c.e') || 5; // non-true default value
* // => 5
*
*/
var dotGet = function (obj, path, def, has) {
return (typeof path === 'string' ? path.split(/[\.\[\]\'\"]/) : path)
.filter(function (p) { return 0 === p ? true : p; })
.reduce(function (o, p) {
return typeof o === 'object' ? ((
has ? o.hasOwnProperty(p) : o[p] !== undefined
) ? o[p] : def) : def;
}, obj);
}
它不像?那样好。运算符,但要实现类似的结果,你可以这样做:
user && user.address && user.address.postcode
因为null和undefined都是假值(参见参考),所以只有当前面的属性不是null或undefined时,才会访问&&运算符后面的属性。
或者,你可以这样写一个函数:
function _try(func, fallbackValue) {
try {
var value = func();
return (value === null || value === undefined) ? fallbackValue : value;
} catch (e) {
return fallbackValue;
}
}
用法:
_try(() => user.address.postcode) // return postcode or undefined
或者,使用回退值:
_try(() => user.address.postcode, "none") // return postcode or a custom string
一个安全的deep get方法似乎很适合underscore.js,但问题是要避免字符串编程。修改@Felipe的答案以避免字符串编程(或至少将边缘情况推回调用者):
function safeGet(obj, props) {
return (props.length==1) ? obj[keys[0]] :safeGet(obj[props[0]], props.slice(1))
}
例子:
var test = {
a: {
b: 'b property value',
c: { }
}
}
safeGet(test, ['a', 'b'])
safeGet(test, "a.b".split('.'))
我认为这个问题在2018年需要重新审视一下。这可以在不使用Object.defineProperty()的任何库的情况下很好地完成,并可以如下使用:
myVariable.safeGet('propA.propB.propC');
我认为这是安全的(而且合乎js-ethical),因为Object的defineProperty方法现在有可写和可枚举的定义,如MDN中所述
函数定义如下:
Object.defineProperty(Object.prototype, 'safeGet', {
enumerable: false,
writable: false,
value: function(p) {
return p.split('.').reduce((acc, k) => {
if (acc && k in acc) return acc[k];
return undefined;
}, this);
}
});
我将一个带有控制台输出的jsBin放在一起来演示这一点。注意,在jsBin版本中,我还为空值添加了一个自定义异常。这是可选的,所以我把它排除在上面的最小定义之外。
欢迎改进