Javascript检查未定义的语义

Javascript checking undefined semantics

本文关键字:语义 未定义 检查 Javascript      更新时间:2023-09-26

我以前看到,在语义上,undefined只应用于已声明但未定义的变量,如果变量在任何时候都应设置或取消设置,我应该首先将其设置为null,并检查变量是否为null,而不是将其设置回undefined。

我想知道我在检查应该未定义的东西的情况,就像在检查对象中未设置的键指向什么的情况一样即

var eva = {'asuka': 2, 'rei': 0};

如果我要检查eva["inji"],我就必须检查是否有未定义的密钥,因为在某些情况下,我不知道要检查的所有可能的密钥。

我想在这种情况下,eva["hinji"]是未定义的是正确的,尽管在对象中键的特定情况下,在eva中使用("sinji")是最好的?然而,我有一种感觉,可能还有其他情况下,未知的对象被检查,我不能使用"in"代替,但对象密钥的情况对我来说最明显。

在这种情况下,最好检查是否未定义?

首先,您的声明不正确,应该是:

var eva = {'asuka': 2, 'rei': ''};

然后你可以找到eva['asuka']eva.asuka会给出2。

如果要检查对象中是否有属性。有多种方法可以做到这一点。

  1. 您可以简单地检查eva && eva.hasOwnProperty('asuka')
  2. eva && typeof(eva.asuka) !== 'undefined'

3.

var found = false;
for (i in eva){
if (i == 'asuka') {
found = true;
break;
}
}

正如mattclemens所评论的,如果您不了解undefinednull的差异和最佳实践,请查看他发布的链接,或其他大量关于此主题的博客/论坛帖子、书籍或视频之一(即,回避类似"js最佳实践未定义null"的内容)。

根据你问题的第一段,你似乎已经理解了它们的意思,这个问题归结为上下文。。。

我想知道我检查的东西应该是未定义的。。。

这对我来说似乎是一个沉重的问题。"应该是未定义的"是什么意思?这告诉我,你的代码从来没有设置"应该是未定义的"属性,并且你假设没有其他人设置它。但实际上,"应该是不定义的"对我来说没有意义。你要么知道这不是因为它从来没有超出当前范围,你自己也没有定义它,您不知道,最好先检查它是否已定义,然后再检查它是否为null

所以我认为这是两个基本场景:

  1. 内部/私人创建并仅在内部用于您控制的代码
  2. 外部/公共创建的跨越公共/专用线

1.仅供内部/私人使用

在第一种情况下,答案很简单:使用对象上所有属性的默认值(回落到null)初始化对象。。。

var eva = {'asuka': 2, 'rei': null};

或者,由于您可以在对象的整个生命周期中直接控制它,因此可以根据需要使用默认运算符显式添加属性。。。

eva.shinji = eva.shinji || null;

然后,每当您需要检查特定属性的值时,您唯一关心的是它是否为null。您会注意到,在一些使用最广泛的js库中使用了这种策略,例如jQuery,其中内部变量只根据null进行检查,甚至假设存在于某些上下文中。

2.对象生命周期中任何时候的外部/公共使用

对于你不能信任的对象,我建议有两种方法,选择哪一种取决于上下文的细节。如果您正在接收某个对象,并且将重复使用该对象,或者修改从中接收的数据仅供内部使用,或者如果以任何方式更改原始对象的值都不安全,则您可能需要制作自己的对象副本,然后以独占方式处理该副本。同样,这在库/框架中得到了说明,如jQuery和AngularJS,其中像windowundefined值本身这样的东西被传递给IIFE,并且创建/扩展了一个内部副本,以便在消费者的整个生命周期中进行内部使用。

然而,对于您的情况来说,这可能是不必要的开销。相反,当eva越过外部/内部边界时,您可以只验证它的内容。以下示例使用默认运算符执行此操作。

function yourFunction(eva) {
    eva = eva || {};
    eva.asuka = eva.asuka || 2;
    eva.rei = eva.rei || null;
}

或者,您可能有一个字符串值或字符串值数组,这些值是您希望验证对象上是否存在的键。在这种情况下,请考虑以下使用Object.keys()的示例。此示例还允许未定义键的名称数组。

function foo(eva, keysToFind) {
    eva = eva || {};        
    keysToFind = keysToFind || ['asuka', 'shinji'];
    var keysToCheck = Object.keys(eva);
    for(var k in keysToFind) {
        var keyName = keysToFind[k];
        var keyIdx = keysToCheck.indexOf(keyName);
        if(keyIdx == -1) {
            eva[keyName] = null;
        }
    }
}

最后,正如RaymondM所指出的,如果你需要确定一个属性是添加到对象文字中的,它的原型,还是从超级/基类继承的,你可以更进一步。。。

  1. 你可以简单地检查eva&eva.hasOwnProperty("suka")

同样,考虑到上下文,如果您已经从上面将上下文识别为场景1或2,并且正在检查不止一个属性的存在,那么分别检查=== nulltypeof eva.asuka === 'undefined'可能会更有效。如果您确定已经定义了asuka,甚至可以检查if(eva && eva.asuka) { ... }