Hvordan kan jeg sjekke for "undefined" i JavaScript?
Hva er den mest passende måten å teste om en variabel er udefinert i JavaScript?
Jeg har sett flere mulige måter:
if (window.myVariable)
Eller
if (typeof(myVariable) != "undefined")
Eller
if (myVariable) // This throws an error if undefined. Should this be in Try/Catch?
Svar #1
Hvis du er interessert i å finne ut om en variabel har blitt erklært uavhengig av verdien, er det tryggeste å bruke in-operatoren. Vurder dette eksemplet:
// global scope
var theFu; // theFu has been declared, but its value is undefined
typeof theFu; // "undefined"
Men dette er kanskje ikke det tiltenkte resultatet i noen tilfeller, siden variabelen eller egenskapen ble erklært, men bare ikke initialisert. Bruk in-operatoren for en mer robust sjekk.
"theFu" in window; // true
"theFoo" in window; // false
Hvis du er interessert i å vite om variabelen ikke har blitt deklarert eller har verdien undefined, bruk da typeof-operatoren, som er garantert å returnere en streng:
if (typeof myVar !== 'undefined')
Direkte sammenligninger med undefined er problematiske siden undefined kan overskrives.
window.undefined = "foo";
"foo" == undefined // true
Som @CMS påpekte, har dette blitt fikset i ECMAScript 5. utgave, og undefined kan ikke endres.
if (window.myVar) vil også inkludere disse falske verdiene, så det er ikke veldig robust:
false
0
""
NaN
null
undefined
Takk til @CMS for å påpeke at ditt tredje tilfelle - if (myVariable) også kan kaste en feil i to tilfeller. Det første er når variabelen ikke er blitt definert, noe som kaster en ReferenceError.
// abc was never declared.
if (abc) {
// ReferenceError: abc is not defined
}
Den andre situasjonen er når variabelen har blitt definert, men har en getter-funksjon som kaster en feil når den kalles. For eksempel,
// or it's a property that can throw an error
Object.defineProperty(window, "myVariable", {
get: function() { throw new Error("W00t?"); },
set: undefined
});
if (myVariable) {
// Error: W00t?
}
Svar #2
Jeg bruker personlig
myVar === undefined
Advarsel: Vennligst merk at === brukes i stedet for == og at myVar tidligere har blitt deklarert (ikke definert).
Jeg liker ikke typeof myVar === "undefined". Jeg synes det er omstendelig og unødvendig. (Jeg kan få det samme gjort med mindre kode.)
Nå vil noen mennesker kollapse av smerte når de leser dette, og skrike: "Vent! VEEEENT!!! undefined kan omdefineres!"
Kult. Jeg vet dette. På den annen side kan de fleste variabler i Javascript bli redefinert. Bør du aldri bruke noen innebygde identifikatorer som kan bli redefinert?
Hvis du følger denne regelen, bra for deg: du er ikke en hykler.
Saken er at for å gjøre mye ekte arbeid i JS, må utviklere kunne stole på at redefinerbare identifikatorer er det de er. Jeg hører ikke folk fortelle meg at jeg ikke burde bruke setTimeout fordi noen kan
window.setTimeout = function () {
alert("Got you now!");
};
Konklusjonen er at argumentet «det kan omdefineres» for å ikke bruke en rå === undefined er grunnløst.
(Hvis du fortsatt er redd for at undefined blir redefinert, hvorfor integrerer du blindt utestet bibliotekkode i kodebasen din? Eller enda enklere: et lint-verktøy.)
Også, akkurat som typeof-tilnærmingen, kan denne teknikken "oppdage" udeklarerte variabler:
if (window.someVar === undefined) {
doSomething();
}
Men begge disse teknikkene lekker i deres abstraksjon. Jeg oppfordrer deg til ikke å bruke dette eller engang
if (typeof myVar !== "undefined") {
doSomething();
}
Vurder:
var iAmUndefined;
For å sjekke om den variabelen er deklarert eller ikke, kan det hende du må ty til in-operatoren. (I mange tilfeller kan du enkelt lese koden O_o).
if ("myVar" in window) {
doSomething();
}
Men vent! Det er mer! Hva om det skjer litt prototype-kjede-magi…? Nå er ikke engang den overlegne in-operatoren nok. (Ok, jeg er ferdig med denne delen bortsett fra å si at for 99 % av tiden fungerer === undefined (og ****host**** typeof) helt fint. Hvis du virkelig bryr deg, kan du lese om dette emnet separat.)
Svar #3
2020 Oppdatering
En av grunnene mine til å foretrekke en typeof-sjekk (nemlig at undefined kan omdefineres) ble irrelevant med den massive adopsjonen av ECMAScript 5. Den andre, at du kan bruke typeof for å sjekke typen til en udeklarert variabel, var alltid nisje. Derfor vil jeg nå anbefale å bruke en direkte sammenligning i de fleste situasjoner:
myVariable === undefined
Opprinnelig svar fra 2010
Å bruke typeof er min preferanse. Det vil fungere når variabelen aldri har blitt erklært, i motsetning til enhver sammenligning med == eller ===-operatorene eller typekoercjon ved bruk av if. (undefined, i motsetning til null, kan også bli redefinert i ECMAScript 3-miljøer, noe som gjør det upålitelig for sammenligning, selv om nesten alle vanlige miljøer nå er kompatible med ECMAScript 5 eller nyere).
if (typeof someUndeclaredVariable == "undefined") {
// Works
}
if (someUndeclaredVariable === undefined) {
// Throws an error
}
Svar #4
Du kan bruke typeof, slik:
if (typeof something != "undefined") {
// ...
}
Svar #5
Oppdatering 2018-07-25
Det har gått nesten fem år siden dette innlegget først ble laget, og JavaScript har utviklet seg mye. Når jeg gjentok testene fra det opprinnelige innlegget, fant jeg ingen konsekvent forskjell mellom følgende testmetoder:
abc === undefinedabc === void 0typeof abc == 'undefined'typeof abc === 'undefined'
Selv når jeg endret testene for å hindre at Chrome optimaliserte dem bort, var forskjellene ubetydelige. Derfor vil jeg nå anbefale abc === undefined for klarhet.
Relevant innhold fra chrome://version:
- Google Chrome: 67.0.3396.99 (Offisiell versjon) (64-bit) (kohort: Stabil)
- Revisjon: a337fbf3c2ab8ebc6b64b0bfdce73a20e2e2252b-refs/branch-heads/3396@{#790}
- OS: Windows
- JavaScript: V8 6.7.288.46
- Brukeragent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, som Gecko) Chrome/67.0.3396.99 Safari/537.36
Opprinnelig innlegg 2013-11-01
I Google Chrome var følgende alltid litt raskere enn en typeof-test:
if (abc === void 0) {
// Undefined
}
Forskjellen var ubetydelig. Likevel er denne koden mer konsis, og tydeligere ved et første blikk for noen som vet hva void 0 betyr. Legg merke til at abc må fortsatt erklæres.
Både typeof og void var betydelig raskere enn å sammenligne direkte mot undefined. Jeg brukte følgende testformat i Chrome-utviklerkonsollen:
var abc;
start = +new Date();
for (var i = 0; i < 10000000; i++) {
if (TEST) {
void 1;
}
}
end = +new Date();
end - start;
Resultatene var som følger:
Test: | abc === undefined abc === void 0 typeof abc == 'undefined'
------+---------------------------------------------------------------------
x10M | 13678 ms 9854 ms 9888 ms
x1 | 1367.8 ns 985.4 ns 988.8 ns
Merk at den første raden er i millisekunder, mens den andre raden er i nanosekunder. En forskjell på 3,4 nanosekunder er ingenting. Tidene var ganske konsistente i påfølgende tester.
Svar #6
Hvis det er udefinert, vil det ikke være lik en streng som inneholder tegnene "undefined", siden strengen ikke er udefinert.
Du kan sjekke typen til variabelen:
if (typeof(something) != "undefined") ...
Noen ganger trenger du ikke engang å sjekke typen. Hvis verdien av variabelen ikke kan evalueres til false når den er satt (for eksempel hvis det er en funksjon), kan du bare evaluere variabelen. Eksempel:
if (something) {
something(param);
}
Svar #7
if (typeof foo == 'undefined') {
// Do something
};
Merk at streng sammenligning (!==) ikke er nødvendig i dette tilfellet, siden typeof alltid vil returnere en streng.
Svar #8
Noen scenarier som illustrerer resultatene av de forskjellige svarene: http://jsfiddle.net/drzaus/UVjM4/
(Merk at bruken av var for in-tester gjør en forskjell når det er i en avgrenset wrapper)
Kode for referanse:
(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;
}
})();
Og resultater:
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
Svar #9
I denne artikkelen leste jeg at rammeverk som Underscore.js bruker denne funksjonen:
function isUndefined(obj){
return obj === void 0;
}
Svar #10
Personlig bruker jeg alltid følgende:
var x;
if( x === undefined) {
//Do something here
}
else {
//Do something else here
}
Egenskapen window.undefined er skrivebeskyttet i alle moderne nettlesere (JavaScript 1.8.5 eller nyere). Fra Mozillas dokumentasjon: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined, ser jeg dette: En grunn til å bruke typeof() er at det ikke kaster en feil hvis variabelen ikke har blitt definert.
Jeg foretrekker å ha tilnærmingen med å bruke
x === undefined
fordi det feiler og eksploderer foran ansiktet mitt i stedet for stille å passere/feile hvis x ikke har blitt erklært før. Dette varsler meg om at x ikke er erklært. Jeg mener at alle variabler som brukes i JavaScript bør erklæres.
Svar #11
Den mest pålitelige måten jeg kjenner til for å sjekke etter undefined er å bruke void 0.
Dette er kompatibelt med både nyere og eldre nettlesere, og kan ikke overskrives slik window.undefined kan i noen tilfeller.
if( myVar === void 0){
//yup it's undefined
}
