检查任何对象的“未定义”或“空”

时间:2018-10-02 14:02:37

标签: javascript angular lodash

我正在Angular项目上工作,有时不时检查Object或它的属性上的undefinednull。通常我使用lodash _.isUndefined(),请参见下面的示例:

this.selectedItem.filter(i => {
    if(_.isUndefined(i.id)) {
      this.selectedItem.pop();
    }
})

我看不到任何问题。但是在审查上述代码时,我与同事进行了讨论。他告诉我,如果iundefined语句之前得到if,那么它将引发异常。相反,他建议我总是像这样检查ii.id

if(!!i && !!i.id) {
      this.selectedItem.pop();
}

我坚信他试图说的话不同于他在上述代码中检查undefined的方式。但是后来我在想lodash _.isUndefined的目的是什么?

任何人都可以让我知道最好的或干净的方法是什么。因为对我来说!!i && !!i.id根本不可读。

非常感谢。

10 个答案:

答案 0 :(得分:6)

您可以使用_.isNil()来检测undefinednull。由于您使用的是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等),而不仅是nullundefined

答案 2 :(得分:2)

您可以检查i,如果它不是真实的,或者该属性是undefinednull,请执行某些操作。

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部分应该捕获任何NaNtypeof(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而不是与_.isNillnull比较的==

答案 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'