我正在Angular项目上工作,有时不时检查Object或它的属性上的undefined
或null
。通常我使用lodash _.isUndefined()
,请参见下面的示例:
this.selectedItem.filter(i => {
if(_.isUndefined(i.id)) {
this.selectedItem.pop();
}
})
我看不到任何问题。但是在审查上述代码时,我与同事进行了讨论。他告诉我,如果i
在undefined
语句之前得到if
,那么它将引发异常。相反,他建议我总是像这样检查i
或i.id
:
if(!!i && !!i.id) {
this.selectedItem.pop();
}
我坚信他试图说的话不同于他在上述代码中检查undefined
的方式。但是后来我在想lodash _.isUndefined
的目的是什么?
任何人都可以让我知道最好的或干净的方法是什么。因为对我来说!!i && !!i.id
根本不可读。
非常感谢。
答案 0 :(得分:6)
您可以使用_.isNil()
来检测undefined
或null
。由于您使用的是Array.filter()
,因此您想返回!_.isNil()
的结果。由于i
应该是对象,因此可以使用!_.isNil(i && i.id)
。
注意:您将Array.filter()
用作Array.forEach()
。 Array.filter()
的回调应返回一个布尔值,并且过滤器的结果是一个新数组。
const selectedItem = [
undefined,
{},
{ id: 5 },
undefined,
{ id: 7 },
];
const result = selectedItem.filter(i => !_.isNil(i && i.id));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
您还可以使用_.reject()
并省去添加!
的需要:
const selectedItem = [
undefined,
{},
{ id: 5 },
undefined,
{ id: 7 },
];
const result = _.reject(selectedItem, i => _.isNil(i && i.id));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
答案 1 :(得分:3)
使用typeof i.id === 'undefined'
检查undefined
,用i.id === null
检查null
。
您可以编写自己的辅助函数来包装任何逻辑,例如LoDash所具有的逻辑。带有!!i && !!i.id
的条件仅用于查找虚假值(空字符串,0
等),而不仅是null
或undefined
。
答案 2 :(得分:2)
您可以检查i
,如果它不是真实的,或者该属性是undefined
或null
,请执行某些操作。
if (!i || i.id === undefined || i.id === null) {
this.selectedItem.pop();
}
答案 3 :(得分:2)
引用具有undefined
作为其值的变量不会引发任何错误。您得到ReferenceError
来引用未定义的变量:
> i
Uncaught ReferenceError: i is not defined
如果将未定义的变量传递给函数,则会抛出ReferenceError
,并且该函数将不会执行。
> _.isUndefined(i)
Uncaught ReferenceError: i is not defined
typeof
运算符应用于安全检查变量是否已定义:
> typeof i
'undefined'
在您的代码中定义了i
(它是一个函数参数),因此通过引用它不会得到任何ReferenceError
。定义TypeError
时,代码将抛出i
,具有undefined
值,而您将其视为对象:
> var i = undefined; i.id
Uncaught TypeError: Cannot read property 'id' of undefined
答案 4 :(得分:1)
您的朋友是对的。当您这样做时,_.isUndefined(i.id)
假设i
不是undefined
。您假设i
是一个具有id
属性的对象,您正在检查该属性是否为 falsey 。
当自身为undefined
时会发生什么?因此,您将得到undefined.id
,这是一个错误。因此,您可以简单地做到这一点
if(i && i.id) {
// You're good to go
}
以上内容将检查所有 falsey 值,包括0
和""
。因此,如果您想非常具体,则必须使用typeof
运算符检查两者的类型。
答案 5 :(得分:1)
我可以建议检查一下if(typeof(element) == "number" && element) {}
,在这种情况下,typeof()
部分捕获任何非数字,而element
部分应该捕获任何NaN
(typeof(NaN)
返回“数字”)
答案 6 :(得分:1)
let words = [null, undefined, 'cheaters', 'pan', 'ear', 'era']
console.log(words.filter(word => word != null));
答案 7 :(得分:1)
您可以使用lodash#get(它将处理根是否为null或未定义),然后使用==
或!=
而不是{{ 1}}或===
。如果输出为!==
或null
,则与undefined
进行比较为真,而==
为假。
!=
const selectedItem = [
undefined,
{},
{id: null},
{ id: 5 },
undefined,
{ id: 0 },
{ id: 7 },
];
const res = selectedItem.filter(a => _.get(a, 'id') != null);
console.log(res);
使用lodash#get可以检查是否存在任何嵌套级别,而无需像<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
(在&&
的情况下)这样的后续a && a.b && a.b.c && a.b.c.d
来查看this answer of mine使用lodash#get
此外,您可以使用d
而不是与_.isNill
或null
比较的==
答案 8 :(得分:1)
另一种“活泼”的方法是使用_.conforms。在我看来,可读性要好得多,您可以直接访问> private let bullsEyeSlider: UISlider = {
> let slider = UISlider(frame: CGRect(x: self.view.frame.midX,y:100, width: 500, height: 20))
> slider.minimumValue = 0
> slider.maximumValue = 100
> return slider
> }()
,因此之前的undefined不会出现问题:
id
const items = [
undefined,
{ id: null},
{ id: 5 },
{ id: "4" },
{ id: undefined },
undefined,
{ id: 0 },
{ id: 7 },
{ id: () => 3 }
];
const numbersOnly = _.filter(items, _.conforms({'id': _.isNumber}));
console.log('numbers', numbersOnly);
const allDefined = _.filter(items, _.conforms({'id': _.negate(_.isUndefined)}));
console.log('defined', allDefined);
const stringsOnly = _.filter(items, _.conforms({'id': _.isString}));
console.log('strings', stringsOnly);
const functionsOnly = _.filter(items, _.conforms({'id': _.isFunction}));
console.log('functions', functionsOnly);
答案 9 :(得分:1)
Javascript 现在有(Chrome 80、Safari 13.4)Optional chaining (?.)
<块引用>可选的链接运算符 (?.) 允许读取 a 的值 属性位于连接对象链的深处,没有 必须明确验证链中的每个引用都是 有效。
这意味着如果 i 未定义,您可以检查 id 而不会导致异常
this.selectedItem.filter(i => {
if(i?.id) {
this.selectedItem.pop();
}
})
或者因为您正在使用过滤器,您可以检查 test this live on the filter documentation。
const words = ['spray', undefined, 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word?.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
另外,还值得一提的是,正如@Koushik Chatterjee 的回答要点,lodash _.get 允许您安全地描述深度属性的路径,甚至在它不存在的情况下给出默认值。>
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.get(object, ['a', '0', 'b', 'c']);
// => 3
_.get(object, 'a.b.c', 'default');
// => 'default'