Vraag Een ongedefinieerde objecteigenschap detecteren


Wat is de beste manier om te controleren of een objecteigenschap in JavaScript onbepaald is?


2430
2017-08-26 07:25


oorsprong


antwoorden:


Gebruik:

if (typeof something === "undefined") {
    alert("something is undefined");
}

Als een objectvariabele enkele eigenschappen heeft, kunt u hetzelfde als dit gebruiken:

if (typeof my_obj.someproperties === "undefined"){
    console.log('the property is not available...'); // print into console
}

Sinds ECMAScript 5, undefined kan niet worden overschreven, dus my_obj === undefined zou ook werken, maar alleen als my_obj bestaat. Dit kan al dan niet gewenst zijn omdat je net zo goed kunt gebruiken null als je deze semantiek nodig hebt (zie Wat is het verschil tussen null en undefined in JavaScript?). Voor objecteigenschappen werkt het echter ongeacht of de eigenschap bestaat.


2316
2018-01-06 12:27



Ik geloof dat er een aantal onjuiste antwoorden op dit onderwerp zijn. In tegenstelling tot wat vaak wordt gedacht, is 'undefined' dat wel niet een sleutelwoord in JavaScript en kan in feite een waarde toegewezen krijgen.

Juiste code

De meest robuuste manier om deze test uit te voeren is:

if (typeof myVar === "undefined")

Dit levert altijd het juiste resultaat op en verwerkt zelfs de situatie myVar wordt niet verklaard.

Gedegenereerde code. GEBRUIK NIET.

var undefined = false;  // Shockingly, this is completely legal!
if (myVar === undefined) {
    alert("You have been misled. Run away!");
}

Bovendien, myVar === undefined zal een fout melden in de situatie waarin myVar niet is aangegeven.


803
2017-08-23 18:03



In JavaScript is dat zo nul en daar is onbepaald. Ze hebben verschillende betekenissen.

  • onbepaald betekent dat de variabele waarde niet is gedefinieerd; het is niet bekend wat de waarde is.
  • nul betekent dat de variabele waarde is gedefinieerd en ingesteld op null (heeft geen waarde).

Marijn Haverbeke zegt in zijn gratis, online boek "Eloquent JavaScript"(nadruk van mij):

Er is ook een vergelijkbare waarde, null, waarvan de betekenis is 'deze waarde is gedefinieerd, maar deze heeft geen waarde'. Het verschil in betekenis tussen undefined en nul is meestal academisch en meestal niet erg interessant. In praktische programma's is het vaak nodig om te controleren of iets 'een waarde heeft'. In deze gevallen kan de uitdrukking something == undefined worden gebruikt, omdat, hoewel ze niet exact dezelfde waarde hebben, null == undefined true oplevert.

Dus, ik denk dat de beste manier om te controleren of iets ongedefinieerd was, zou zijn:

if (something == undefined)

Ik hoop dat dit helpt!

Bewerk: In reactie op uw bewerking moeten objecteigenschappen op dezelfde manier werken.

var person = {
    name: "John",
    age: 28,
    sex: "male"
};

alert(person.name); // "John"
alert(person.fakeVariable); // undefined

133
2017-08-26 07:36



Ondanks dat het door vele andere antwoorden hier heftig wordt aanbevolen, typeof  is een slechte keuze. Het mag nooit worden gebruikt om te controleren of variabelen de waarde hebben undefined, omdat het fungeert als een gecombineerde controle voor de waarde undefined en of een variabele bestaat. In de overgrote meerderheid van de gevallen weet u wanneer een variabele bestaat, en typeof introduceert alleen het potentieel voor een stille mislukking als je een typfout maakt in de naam van de variabele of in de letterlijke tekenreeks 'undefined'.

var snapshot = …;

if (typeof snaposhot === 'undefined') {
    //         ^
    // misspelled¹ – this will never run, but it won’t throw an error!
}
var foo = …;

if (typeof foo === 'undefned') {
    //                   ^
    // misspelled – this will never run, but it won’t throw an error!
}

Dus tenzij je feature detection² uitvoert, waarbij het onzeker is of een bepaalde naam in scope zal zijn (zoals controleren) typeof module !== 'undefined' als een stap in code die specifiek is voor een CommonJS-omgeving), typeof is een schadelijke keuze bij gebruik op een variabele en de juiste optie is om de waarde rechtstreeks te vergelijken:

var foo = …;

if (foo === undefined) {
    ⋮
}

Enkele veel voorkomende misvattingen hierover zijn:

  • dat het lezen van een "niet-geïnitialiseerde" variabele (var foo) of parameter (function bar(foo) { … }, genaamd as bar()) zal mislukken. Dit is gewoon niet waar - variabelen zonder expliciete initialisatie en parameters die geen waarden kregen, worden altijd undefined, en zijn altijd in omvang.

  • dat undefined kan worden overschreven. Er is nog veel meer aan de hand. undefined is geen trefwoord in JavaScript. In plaats daarvan is het een eigenschap op het globale object met de ongedefinieerde waarde. Echter sinds ES5 is deze eigenschap geweest alleen lezen en niet-configureerbare. Geen enkele moderne browser zal het toestaan undefined eigendom dat moet worden gewijzigd en vanaf 2017 is dit al lang het geval. Gebrek aan strikte modus heeft geen invloed op undefinedZijn gedrag - het maakt alleen uitspraken als undefined = 5 niets doen in plaats van gooien. Omdat het geen trefwoord is, kunt u dat wel verklaren variabelen met de naam undefineden die variabelen kunnen worden gewijzigd, waardoor dit eens zo gemeenschappelijke patroon wordt gemaakt:

    (function (undefined) {
        // …
    })()
    

    meer gevaarlijker dan het gebruik van de global undefined. Als je ES3-compatibel moet zijn, vervang je undefined met void 0 - neem geen toevlucht tot typeof. (void is altijd een unaire operator geweest die evalueert naar de Undefined-waarde voor elke operand.)

Met hoe variabelen uit de weg werken, is het tijd om de eigenlijke vraag aan te pakken: objecteigenschappen. Er is geen reden om ooit te gebruiken typeof voor objecteigenschappen. De eerdere uitzondering betreffende kenmerkdetectie is hier niet van toepassing - typeof heeft alleen speciaal gedrag op variabelen en uitdrukkingen die verwijzen naar objecteigenschappen zijn geen variabelen.

Deze:

if (typeof foo.bar === 'undefined') {
    ⋮
}

is altijd precies hetzelfde naar deze³:

if (foo.bar === undefined) {
    ⋮
}

en rekening houdend met het bovenstaande advies, om te voorkomen dat lezers in de war raken over waarom u het gebruikt typeof, omdat het het meest zinvol is om te gebruiken === om te controleren op gelijkheid, omdat het kan worden aangepast om de waarde van een variabele later te controleren en omdat het er gewoon beter uitziet, je moet altijd gebruiken === undefinedŁ ook hier.

Iets anders om te overwegen als het gaat om objecteigenschappen is of u echt wilt controleren undefined helemaal niet. Een gegeven eigenschapsnaam kan afwezig zijn op een object (de waarde produceren undefined wanneer gelezen), aanwezig op het object zelf met de waarde undefined, aanwezig op het prototype van het object met de waarde undefined, of aanwezig in een van beide met een niet-undefined waarde. 'key' in obj zal u vertellen of een sleutel zich ergens in de prototypeketen van een object bevindt, en Object.prototype.hasOwnProperty.call(obj, 'key') zal je vertellen of het direct op het object is. Ik zal niet in detail ingaan op dit antwoord over prototypes en het gebruik van objecten als kaarten met snaren, omdat het vooral bedoeld is om alle slechte adviezen in andere antwoorden tegen te gaan, ongeacht de mogelijke interpretaties van de oorspronkelijke vraag. Lees verder object prototypen op MDN voor meer!

¹ Ongebruikelijke keuze van de naam van de voorbeeldvariabele? dit is echte dode code van de NoScript-extensie voor Firefox.
² ga er niet vanuit dat het niet goed is om te weten wat er in de scope zit. bonuskwetsbaarheid veroorzaakt door misbruik van dynamische scope: Project Zero 1225
³ wederom uitgaande van een ES5 + -omgeving en dat undefined verwijst naar de undefined eigendom van het globale object. plaatsvervanger void 0 anders.


130
2018-02-26 21:17



Wat betekent dit: "ongedefinieerde objecteigenschap"?

Eigenlijk kan het twee heel verschillende dingen betekenen! Ten eerste kan het betekenen de eigenschap die nog nooit is gedefinieerd in het object en ten tweede kan het het eigenschap die een ongedefinieerde waarde heeft. Laten we naar deze code kijken:

var o = { a: undefined }

is o.a undefined? Ja! De waarde is niet gedefinieerd. is o.b undefined? Zeker! Er is helemaal geen eigenschap 'b'! OK, kijk nu hoe verschillende benaderingen zich gedragen in beide situaties:

typeof o.a == 'undefined' // true
typeof o.b == 'undefined' // true
o.a === undefined // true
o.b === undefined // true
'a' in o // true
'b' in o // false

Dat kunnen we duidelijk zien typeof obj.prop == 'undefined' en obj.prop === undefined zijn gelijkwaardig, en ze onderscheiden die verschillende situaties niet. En 'prop' in obj kan de situatie detecteren wanneer een eigenschap helemaal niet is gedefinieerd en let niet op de eigenschapswaarde die mogelijk ongedefinieerd is.

Dus wat te doen?

1) U wilt weten of een eigenschap niet gedefinieerd is door de eerste of tweede betekenis (de meest typische situatie).

obj.prop === undefined // IMHO, see "final fight" below

2) U wilt gewoon weten of een object een eigenschap heeft en niet geïnteresseerd is in de waarde ervan.

'prop' in obj

Opmerkingen:

  • U kunt een object en de bijbehorende eigenschap niet tegelijkertijd controleren. Bijvoorbeeld dit x.a === undefined of dit typeof x.a == 'undefined' raises ReferenceError: x is not defined als x niet is gedefinieerd.
  • veranderlijk undefined is een globale variabele (zo is het eigenlijk window.undefined in browsers). Het is ondersteund sinds ECMAScript 1e editie en sinds ECMAScript 5 het is alleen lezen. Dus in moderne browsers kan dit niet zo zijn geherdefinieerd tot waar zoveel auteurs houden ervan ons angst aan te jagen, maar dit is nog steeds waar voor oudere browsers.

Laatste gevecht: obj.prop === undefined vs typeof obj.prop == 'undefined'

Pluspunten van obj.prop === undefined:

  • Het is een beetje korter en ziet er een beetje mooier uit
  • De JavaScript-engine geeft een foutmelding als je een spelfout hebt gemaakt undefined

Minpuntjes van obj.prop === undefined:

  • undefined kan worden opgeheven in oude browsers

Pluspunten van typeof obj.prop == 'undefined':

  • Het is echt universeel! Het werkt in nieuwe en oude browsers.

Minpuntjes van typeof obj.prop == 'undefined':

  • 'undefned' (verkeerd gespeld) hier is slechts een stringconstante, dus de JavaScript-engine kan je niet helpen als je het verkeerd gespeld hebt zoals ik net deed.

Update (voor JavaScript op de server):

Node.js ondersteunt de globale variabele undefined als global.undefined (het kan ook worden gebruikt zonder het voorvoegsel 'global'). Ik ben niet op de hoogte van andere implementaties van JavaScript aan de serverzijde.


100
2017-08-08 20:28



De kwestie komt neer op drie gevallen:

  1. Het object heeft de eigenschap en de waarde is dat niet undefined.
  2. Het object heeft de eigenschap en de waarde ervan is undefined.
  3. Het object heeft niet de eigenschap.

Dit vertelt ons iets dat ik belangrijk vind:

Er is een verschil tussen een niet-gedefinieerd lid en een gedefinieerd lid met een ongedefinieerde waarde.

Maar ongelukkig typeof obj.foo vertelt ons niet welke van de drie gevallen we hebben. We kunnen dit echter combineren met "foo" in objom de gevallen te onderscheiden.

                               |  typeof obj.x === 'undefined' | !("x" in obj)
1.                     { x:1 } |  false                        | false
2.    { x : (function(){})() } |  true                         | false
3.                          {} |  true                         | true

Het is vermeldenswaard dat deze tests hetzelfde zijn voor null ingangen ook

                               |  typeof obj.x === 'undefined' | !("x" in obj)
                    { x:null } |  false                        | false

Ik zou zeggen dat het in sommige gevallen logischer is (en is duidelijker) om te controleren of het onroerend goed er is, dan te controleren of het ongedefinieerd is, en het enige geval waarin deze controle anders is, is geval 2, het zeldzame geval van een daadwerkelijke invoer in het object met een ongedefinieerde waarde.

Bijvoorbeeld: ik heb zojuist een heleboel code herschreven met een aantal controles of een object een bepaalde eigenschap had.

if( typeof blob.x != 'undefined' ) {  fn(blob.x); }

Dat was duidelijker wanneer het werd geschreven zonder een vinkje voor undefined.

if( "x" in blob ) { fn(blob.x); }

Maar zoals gezegd zijn deze niet precies hetzelfde (maar zijn meer dan goed genoeg voor mijn behoeften).


59
2018-06-08 04:04



if ( typeof( something ) == "undefined") 

Dit werkte voor mij terwijl de anderen dat niet deden.


38
2017-07-27 16:03



Ik weet niet zeker waar de oorsprong van het gebruik ligt === met typeof kwam van, en als conventie zie ik het in veel bibliotheken worden gebruikt, maar de operator type geeft een letterlijke tekenreeks terug, en dat weten we van voren, dus waarom zou je dit ook willen typen, controleer het dan ook?

typeof x;                      // some string literal "string", "object", "undefined"
if (typeof x === "string") {   // === is redundant because we already know typeof returns a string literal
if (typeof x == "string") {    // sufficient

33
2017-09-22 14:20



Crossposten van mijn antwoord van gerelateerde vraag Hoe te controleren op "undefined" in JavaScript?

Specifiek voor deze vraag, zie testgevallen met someObject.<whatever>.


Enkele scenario's ter illustratie van de resultaten van de verschillende antwoorden: http://jsfiddle.net/drzaus/UVjM4/

(Merk op dat het gebruik van var voor in testen maken het verschil in een scoped wikkel)

Code voor referentie:

(function(undefined) {
    var definedButNotInitialized;
    definedAndInitialized = 3;
    someObject = {
        firstProp: "1"
        , secondProp: false
        // , undefinedProp not defined
    }
    // var notDefined;

    var tests = [
        'definedButNotInitialized in window',
        'definedAndInitialized in window',
        'someObject.firstProp in window',
        'someObject.secondProp in window',
        'someObject.undefinedProp in window',
        'notDefined in window',

        '"definedButNotInitialized" in window',
        '"definedAndInitialized" in window',
        '"someObject.firstProp" in window',
        '"someObject.secondProp" in window',
        '"someObject.undefinedProp" in window',
        '"notDefined" in window',

        'typeof definedButNotInitialized == "undefined"',
        'typeof definedButNotInitialized === typeof undefined',
        'definedButNotInitialized === undefined',
        '! definedButNotInitialized',
        '!! definedButNotInitialized',

        'typeof definedAndInitialized == "undefined"',
        'typeof definedAndInitialized === typeof undefined',
        'definedAndInitialized === undefined',
        '! definedAndInitialized',
        '!! definedAndInitialized',

        'typeof someObject.firstProp == "undefined"',
        'typeof someObject.firstProp === typeof undefined',
        'someObject.firstProp === undefined',
        '! someObject.firstProp',
        '!! someObject.firstProp',

        'typeof someObject.secondProp == "undefined"',
        'typeof someObject.secondProp === typeof undefined',
        'someObject.secondProp === undefined',
        '! someObject.secondProp',
        '!! someObject.secondProp',

        'typeof someObject.undefinedProp == "undefined"',
        'typeof someObject.undefinedProp === typeof undefined',
        'someObject.undefinedProp === undefined',
        '! someObject.undefinedProp',
        '!! someObject.undefinedProp',

        'typeof notDefined == "undefined"',
        'typeof notDefined === typeof undefined',
        'notDefined === undefined',
        '! notDefined',
        '!! notDefined'
    ];

    var output = document.getElementById('results');
    var result = '';
    for(var t in tests) {
        if( !tests.hasOwnProperty(t) ) continue; // bleh

        try {
            result = eval(tests[t]);
        } catch(ex) {
            result = 'Exception--' + ex;
        }
        console.log(tests[t], result);
        output.innerHTML += "\n" + tests[t] + ": " + result;
    }
})();

En resultaten:

definedButNotInitialized in window: true
definedAndInitialized in window: false
someObject.firstProp in window: false
someObject.secondProp in window: false
someObject.undefinedProp in window: true
notDefined in window: Exception--ReferenceError: notDefined is not defined
"definedButNotInitialized" in window: false
"definedAndInitialized" in window: true
"someObject.firstProp" in window: false
"someObject.secondProp" in window: false
"someObject.undefinedProp" in window: false
"notDefined" in window: false
typeof definedButNotInitialized == "undefined": true
typeof definedButNotInitialized === typeof undefined: true
definedButNotInitialized === undefined: true
! definedButNotInitialized: true
!! definedButNotInitialized: false
typeof definedAndInitialized == "undefined": false
typeof definedAndInitialized === typeof undefined: false
definedAndInitialized === undefined: false
! definedAndInitialized: false
!! definedAndInitialized: true
typeof someObject.firstProp == "undefined": false
typeof someObject.firstProp === typeof undefined: false
someObject.firstProp === undefined: false
! someObject.firstProp: false
!! someObject.firstProp: true
typeof someObject.secondProp == "undefined": false
typeof someObject.secondProp === typeof undefined: false
someObject.secondProp === undefined: false
! someObject.secondProp: true
!! someObject.secondProp: false
typeof someObject.undefinedProp == "undefined": true
typeof someObject.undefinedProp === typeof undefined: true
someObject.undefinedProp === undefined: true
! someObject.undefinedProp: true
!! someObject.undefinedProp: false
typeof notDefined == "undefined": true
typeof notDefined === typeof undefined: true
notDefined === undefined: Exception--ReferenceError: notDefined is not defined
! notDefined: Exception--ReferenceError: notDefined is not defined
!! notDefined: Exception--ReferenceError: notDefined is not defined

19
2018-01-13 17:43