简体   繁体   English

JavaScript检查未定义的语义

[英]Javascript checking undefined semantics

I've seen before that undefined semantically should only be used for variables that have been declared but not defined, and if a variable should at any point be set or unset, I should initially set it to null and check the variable against null rather than setting it back to undefined. 我之前看到过,未定义的语义仅应用于已声明但未定义的变量,并且如果应在任何时候设置或取消设置变量,则应首先将其设置为null并检查该变量是否为null而不是将其设置回undefined。

I'm wondering about the case where I am checking something that should be undefined, as in the case I am checking what an unset key in an object points to ie 我想知道我正在检查应该未定义的内容的情况,例如我正在检查对象中未设置的键指向什么

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

if I were to check eva['shinji'], I would have to check for undefined, because there are cases where I would not know all the possible keys that would be checked against. 如果我要检查eva ['shinji'],则必须检查未定义的,因为在某些情况下,我不知道将要检查的所有可能的键。

I guess in this case, eva['shinji'] being undefined would be correct, though in the specific case of keys in objects, using ('shinji' in eva) would be best? 我猜在这种情况下,未定义eva ['shinji']是正确的,尽管在对象键的特定情况下,使用(eva中的'shinji')最好? However, I have a feeling there may be other cases where objects that were unknown were checked against, that I could not use a 'in' for instead, but the case of object keys was most apparent to me. 但是,我感觉可能还有其他情况下,检查未知对象的情况是,我不能使用'in'代替,但是对我来说,对象键的情况最为明显。

In those cases, would it be best to check for undefined? 在这种情况下,最好检查未定义的内容吗?

First of all, your statement is incorrect, should be: 首先,您的陈述不正确,应为:

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

Then you can find eva['asuka'] or eva.asuka will give 2. 然后您可以找到eva['asuka'] eva.asuka eva['asuka']eva.asuka将给出2。

If you want to check if a property inside an object. 如果要检查对象内部是否有属性。 There are multiple ways to do that. 有多种方法可以做到这一点。

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

3. 3。

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

As mattclemens commented, if you do not understand the differences and best practices surrounding undefined vs null please check out the link he posted, or one of the other multitudes of blog/forum posts, books, or videos regarding this subject (ie duckduck something like "js best practices undefined null"). 正如Mattclemens评论的那样,如果您不了解围绕undefinednull的区别和最佳实践,请查看他发布的链接,或与此主题相关的其他众多博客/论坛帖子,书籍或视频之一(例如,duckduck之类的“ js最佳做法未定义null”)。

Based on the first paragraph of your question it seems you have a grasp on what they mean, and this question comes down to context... 根据问题的第一段,您似乎对它们的含义有所了解,并且这个问题取决于上下文。

I'm wondering about the case where I am checking something that should be undefined... 我想知道我正在检查应该未定义的内容的情况...

This seems like a loaded question to me. 对我来说,这似乎是一个充满挑战的问题。 What does "should be undefined" mean? “应该未定义”是什么意思? This tells me that your code never sets that property that "should be undefined" and you are assuming nothing else is setting it. 这告诉我,您的代码永远不会设置“应未定义”的属性,并且您假设没有其他设置。 But really, "should be undefined" doesn't make sense to me. 但是实际上,“应该不确定”对我来说没有意义。 You either know it's not because it's never been outside the current scope and you haven't defined it yourself, or you don't know and it's best practice to check whether it's defined before checking if it's null . 您要么知道不是因为它从来没有超出当前范围,而且您还没有自己定义它, 要么您不知道,并且最佳实践是在检查它是否为null之前检查它是否已定义。

So I see this as 2 basic scenarios: 所以我认为这是2种基本情况:

  1. Internally/Privately created and used exclusively internal to code you control 在内部/私人创建并专用于内部控制代码
  2. Externally/Publicly created or crossing the public/private line 外部/公共创建跨越公共/私有线

1. Internal/Private use only 1.仅供内部/私人使用

In the first scenario the answer is simple: initialize the object with default values (falling back to null ) for all properties that will ever exist on the object... 在第一种情况下,答案很简单:使用对象上将存在的所有属性的默认值初始化对象(返回到null )。

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

...or since you have direct control over the object throughout its lifecycle, add properties explicitly as needed using the default operator... ...或者由于您可以在对象的整个生命周期中直接控制该对象,因此可以使用默认运算符根据需要显式添加属性...

eva.shinji = eva.shinji || null;

Then whenever you need to check the value of a specific property, your only concern is whether it is null . 然后,每当需要检查特定属性的值时,您唯一关心的就是它是否为null You will notice this strategy being employed in some of the most widely used js libraries, such as jQuery, where internal variables are only ever checked against null , or even assumed to exist within some contexts. 您会注意到这种策略已在某些使用最广泛的js库(例如jQuery)中采用,其中仅对内部变量进行过null检验,甚至假定它们存在于某些上下文中。

2. External/Public use at any point in the object's lifecycle 2.在对象生命周期的任何时候进行外部/公共使用

For objects you can't trust there are two approaches I would suggest, and which one is choosen depends, again, on the details of the context. 对于您不信任的对象,我建议使用两种方法,选择哪种方法又取决于上下文的细节。 If you are receiving some object, and will be using that object repeatedly or modifying the data you receive from it for internal use only, or if it is unsafe to change the value of the original object in any way, you may want to make your own copy of the object and then deal with that copy exclusively. 如果您正在接收某个对象,并且将重复使用该对象或修改从该对象接收的数据仅用于内部使用,或者如果以任何方式更改原始对象的值都不安全,则可能需要使拥有对象的副本,然后专门处理该副本。 Again, this is illustrated in libraries/frameworks, such as jQuery and AngularJS, where things like window and the undefined value itself, are passed in to the IIFE, and an internal copy is created/extended for internal use throughout the lifetime of the consumer. 再次,在jQuery和AngularJS等库/框架中对此进行了说明,其中将诸如windowundefined值本身之类的内容传递给IIFE,并创建/扩展了内部副本以供整个消费者使用期间使用。

However, this may be unnecessary overhead for your situation. 但是,对于您的情况,这可能是不必要的开销。 Instead you could just verify the contents of eva when it crosses that external/internal boundary. 相反,您可以在eva越过外部/内部边界时验证eva的内容。 The following example does so with the default operator. 下面的示例使用默认运算符执行此操作。

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

Alternatively, you may have a string value or array of string values that are keys you wish to verify exist on the object. 或者,您可能具有一个字符串值或字符串值数组,这些字符串或数组是您希望验证的键是否存在于对象上。 In that case please consider the following example using Object.keys() . 在这种情况下,请考虑使用Object.keys()的以下示例。 This example also allows for the array of names of keys to be undefined. 此示例还允许未定义键名称的数组。

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;
        }
    }
}

Finally, as RaymondM points out, you can take this a step further if you need to determine whether a property was added to the object literal, it's prototype, or inherited from a super/base class... 最后,正如RaymondM指出的那样,如果需要确定是否将属性添加到对象文字,它是原型还是从父类/基类继承的,则可以更进一步。

  1. You can simple check eva && eva.hasOwnProperty('asuka') 您可以简单地检查eva && eva.hasOwnProperty('asuka')

Again, taking context in to consideration, if you have already identified the context as scenario 1 or 2 from above, and are checking any more than a single property's existence , then it will likely be more efficient to check for === null or typeof eva.asuka === 'undefined' , respectively. 再次考虑到上下文,如果您已经从上方将上下文标识为方案1或2, 并且正在检查的属性不只是单个属性的存在 ,那么检查=== nulltypeof eva.asuka === 'undefined'可能更有效。 typeof eva.asuka === 'undefined' Or even check if(eva && eva.asuka) { ... } , if you're certain asuka has been defined. 甚至检查if(eva && eva.asuka) { ... }如果你一定asuka已经定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM