Czy mogę ustawić zmienne na niezdefiniowane lub przekazać niezdefiniowane jako argument?


304

Jestem trochę zdezorientowany co do JavaScript undefinedi nullwartości.

Co if (!testvar)właściwie robi? Czy testuje undefinedi nullczy tylko undefined?

Czy po zdefiniowaniu zmiennej mogę ją wyczyścić ponownie undefined(a zatem usunąć zmienną)?

Czy mogę przekazać undefinedjako parametr? Na przykład:

function test(var1, var2, var3) {

}

test("value1", undefined, "value2");

Odpowiedzi:


513

Jestem trochę zdezorientowany, że JavaScript jest niezdefiniowany i zerowy.

Nie myl się null. Zasadniczo ma to sens i zachowuje się podobnie do innych pojęć w językach skryptowych obiektów pozapasmowych „zerowych”, „zerowych” lub „brakowych”.

undefinedz drugiej strony jest dziwnym dziwactwem JavaScript. Jest to obiekt singletonowy reprezentujący wartości poza pasmem, zasadniczo drugi podobny, ale inny null. Pojawia się:

  1. Gdy wywołujesz funkcję z mniejszą liczbą argumentów niż lista argumentów na functionlistach instrukcji, argumenty niepasowane są ustawiane na undefined. Możesz to sprawdzić za pomocą np .:

    function dosomething(arg1, arg2) {
        if (arg2===undefined)
        arg2= DEFAULT_VALUE_FOR_ARG2;
        ...
    }

    Dzięki tej metodzie nie można odróżnić dosomething(1)i dosomething(1, undefined); arg2będzie w obu przypadkach taka sama. Jeśli chcesz powiedzieć różnicę, na którą możesz spojrzeć arguments.length, ale takie opcjonalne argumenty nie są ogólnie bardzo czytelne.

  2. Gdy funkcja nie ma return value;, zwraca undefined. Zasadniczo nie ma potrzeby korzystania z takiego zwrotu.

  3. Gdy deklarujesz zmienną, mając var ainstrukcję w bloku, ale jeszcze jej nie przypisałeś, to tak jest undefined. Znów nie powinieneś nigdy polegać na tym.

  4. Upiorny typeofoperator powraca, 'undefined'gdy jego operand jest prostą zmienną, która nie istnieje, zamiast zgłaszania błędu, co normalnie by się zdarzyło, gdybyś próbował się do niego odwołać. (Możesz także nadać mu prostą zmienną owiniętą w nawiasy, ale nie pełne wyrażenie zawierające nieistniejącą zmienną.) Niewiele też do tego służy.

  5. To jest kontrowersyjne. Kiedy uzyskujesz dostęp do właściwości obiektu, który nie istnieje, nie pojawia się od razu błąd, jak w każdym innym języku. Zamiast tego dostajesz undefinedprzedmiot. (A potem, gdy spróbujesz użyć tego undefinedobiektu w dalszej części skryptu, popełni błąd w dziwny sposób, który jest znacznie trudniejszy do wyśledzenia, niż gdyby JavaScript natychmiast wyrzucił błąd).

    Jest to często używane do sprawdzania istnienia właściwości:

    if (o.prop!==undefined) // or often as truthiness test, if (o.prop)
       ...do something...

    Ponieważ jednak możesz przypisać undefineddowolną inną wartość:

    o.prop= undefined;

    nie wykrywa to, czy właściwość jest tam niezawodnie. Lepiej użyć inoperatora, który nie był w oryginalnej wersji JavaScript Netscape, ale jest teraz dostępny wszędzie:

    if ('prop' in o)
        ...

Podsumowując, undefinedjest bałagan specyficzny dla JavaScript, który myli wszystkich. Oprócz opcjonalnych argumentów funkcji, w których JS nie ma bardziej eleganckiego mechanizmu, undefinednależy unikać. To nigdy nie powinno być częścią języka; nulldziałałoby dobrze dla (2) i (3), a (4) to błąd, który istnieje tylko dlatego, że na początku JavaScript nie miał wyjątków.

co if (!testvar)właściwie robi Czy testuje na niezdefiniowany i zerowy czy po prostu niezdefiniowany?

Taki „truthiness” test sprawdza przeciwko false, undefined, null, 0, NaNi puste struny. Ale w tym przypadku tak, to tak naprawdę undefineddotyczy. IMO, powinno to być bardziej jednoznaczne i powiedzieć if (testvar!==undefined).

po zdefiniowaniu zmiennej mogę wyczyścić ją z powrotem do niezdefiniowanej (a zatem usunąć zmienną).

Z pewnością możesz undefineddo niego przypisać , ale to nie spowoduje usunięcia zmiennej. Tylko delete object.propertyoperator naprawdę usuwa rzeczy.

deletejest naprawdę przeznaczony dla właściwości, a nie zmiennych jako takich. Przeglądarki pozwolą ci uciec prosto delete variable, ale nie jest to dobry pomysł i nie będzie działać w trybie ścisłym ECMAScript Piątej Edycji. Jeśli chcesz zwolnić odniesienie do czegoś, aby można je było zebrać w śmieciach, bardziej normalne byłoby powiedzenie variable= null.

czy mogę przekazać niezdefiniowany parametr?

Tak.


10
Co za fantastyczna odpowiedź. Właśnie nie zdałem testu JavaScript: perfectionkills.com/javascript-quiz Później ponownie przeczytam twoją odpowiedź i spróbuję ponownie przetestować!
Skilldrick

1
naprawione, ta. (Zwykle nie martwię się zbytnio o zmianę przydziału, ponieważ jest tak wiele rzeczy, które skrypt może przedefiniować, aby wszystko zepsuć, że nie można rozwiązać ogólnego przypadku.)
Bob

2
@ Bobin undefinedjest obiektem singletonowym? Co masz na myśli? To prymitywna wartość, a nie obiekt.
Šime Vidas,

2
@Hortitude: To jest punkt (4). Generalnie nie chciałbym typeof foo=='undefined'; zwykle używa się go do (4a) globalnego wąchania, w którym to przypadku wolałbym być jawnym i powiedzieć 'foo' in window, lub (4b) testowania względem undefinedsamej wartości, w którym to przypadku wolałbym być czytelny i powiedzieć foo===undefined. Teoretycznie testowanie typeofprzeciwko 'undefined'może mieć przypadek użycia, którego inne konstrukty nie mogłyby zapewnić: wąchanie istnienia zmiennych lokalnych. Jednak w rzeczywistości prawie zawsze wiesz, jakie zmienne są deklarowane jako lokalne.
bobince

4
Jedno zastrzeżenie z numerem 2, zwykle funkcja bez returninstrukcji zwraca undefined, ale jeśli funkcja jest konstruktorem (wywołana przez newoperatora), zwróci nowy obiekt (wartość thiswewnątrz konstruktora), mimo że nie ma returninstrukcji. console.log((function (){}()));zwraca undefined. console.log((new function (){}()));zwraca obiekt.
Bezużyteczny kod

18

Nie możesz (nie powinieneś?) Definiować czegokolwiek jako niezdefiniowanego, ponieważ zmienna nie byłaby już niezdefiniowana - po prostu ją zdefiniowałeś .

Nie możesz (nie powinieneś?) Przejść undefineddo funkcji. Jeśli chcesz przekazać pustą wartość, użyj nullzamiast tego.

Instrukcja if(!testvar)sprawdza logiczne wartości prawda / fałsz, ta konkretna sprawdza, czy testvarocenia false. Z definicji, nulla undefinednie powinny być oceniane jako ani trueczy false, ale analizuje schemat JavaScript nulljak falsei daje błąd, jeśli starają się ocenić niezdefiniowanej zmiennej.

Aby poprawnie przetestować undefinedlub nullużyj:

if(typeof(testvar) === "undefined") { ... }

if(testvar === null) { ... }

1
Potrójny-równy sprawdza również typ, więc nie jest przeprowadzany przymus typu. Douglas Crockford odradza stosowanie operatorów wymuszania typu ( ==i !=).
Skilldrick,

3
Możesz zdefiniować coś jako niezdefiniowany. var a= undefined. Możesz przejść fn(undefined). Jeśli chcesz znaleźć różnicę między niezdefiniowaną właściwością pobiektu o, a właściwością p, która zdefiniowała i ustawiła wartość undefined, musisz użyć 'p' in ooperatora.
bobince

1
Czy istnieje powód, dla którego nie należy przeprowadzać testów testvar === undefinedzamiast bardziej skomplikowanych typeof(testvar) === "undefined"?
ddaa

4
Jest jeszcze jeden dobry powód, aby użyć typeoftestu dla niezdefiniowanych zmiennych: w przeciwieństwie do tego null, undefinedjest po prostu własnością obiektu globalnego i może zostać ponownie zdefiniowany. Wymaga tylko określonego stylu kodowania i brakującego znaku równości i undefinedjest cicho zmieniany:if (undefined = someVar) {...}
Tim Down

1
@IanGrainger: ECMAScript 5 (zaimplementowany w aktualnych wersjach wszystkich przeglądarek) głównie to rozwiązuje, czyniąc undefinedniezmienną właściwość obiektu globalnego, dzięki czemu jest bezpieczniejszy niż kiedyś. Jednak nadal można zdefiniować zmienną zmienną wywoływaną undefinedw funkcji, więc problem nie zniknął całkowicie.
Tim Down

13

Podstawową różnicą jest to, że undefinedi nullreprezentują różne koncepcje.

Gdyby tylko nullbył dostępny, nie byłbyś w stanie ustalić, czy nullzostał ustawiony celowo jako wartość, czy też wartość nie została jeszcze ustawiona, chyba że użyjesz kłopotliwego wychwytywania błędów: np.

var a;

a == null; // This is true
a == undefined; // This is true;
a === undefined; // This is true;

Jeśli jednak celowo ustawisz wartość na null, ścisła równość z undefinednieudanymi, umożliwiając w ten sposób rozróżnienie między wartościami nulli undefinedwartościami:

var b = null;
b == null; // This is true
b == undefined; // This is true;
b === undefined; // This is false;

Sprawdź tutaj referencje zamiast polegać na tym, że ludzie lekceważąco mówią śmieci: „Podsumowując, niezdefiniowany jest bałagan specyficzny dla JavaScript, który myli wszystkich”. To, że jesteś zdezorientowany, nie oznacza, że ​​jest to bałagan.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined

Takie zachowanie nie jest specyficzna dla JavaScript i uzupełnia uogólnionego pojęcia, że wynik może być logiczna true, false, nieznane ( null), bez wartości ( undefined), czy coś poszło nie tak ( error).

http://en.wikipedia.org/wiki/Undefined_value


I nadal nulldziałałoby dobrze. a == nulljest to truespowodowane przymusem typu Javascript.
sleepwalkerfx

11

Najlepszym sposobem sprawdzenia wartości null jest

if ( testVar !== null )
{
    // do action here
}

i dla niezdefiniowanych

if ( testVar !== undefined )
{
    // do action here
}

Możesz przypisać zmienną z niezdefiniowanym.

testVar = undefined;
//typeof(testVar) will be equal to undefined.

1
Najlepszym sposobem sprawdzenia wartości null jest użycie !==, a nie!=
MBO

6

TAK, możesz, ponieważ niezdefiniowany jest zdefiniowany jako niezdefiniowany.

console.log(
   /*global.*/undefined === window['undefined'] &&
   /*global.*/undefined === (function(){})() &&
   window['undefined']  === (function(){})()
) //true

Twój przypadek:

test("value1", undefined, "value2")

możesz również utworzyć własną niezdefiniowaną zmienną:

Object.defineProperty(this, 'u', {value : undefined});
console.log(u); //undefined

5

Aby odpowiedzieć na twoje pierwsze pytanie, operator not ( !) wymusi wszystko, co zostanie podane, na wartość boolowską. Więc null, 0, false, NaNi ""(pusty ciąg znaków) będzie wszystko pojawiać fałszywe.


A także pusty ciąg i NaN (nie liczba)
MBO

undefinednie pojawi się jako false, spowoduje wygenerowanie błędu „nie zdefiniowano”.
Tatu Ulmanen

Tatu Ulmanen: nieprawda. if (undefined) {/* Do stuff*/}nie da błędu, ponieważ undefinedistnieje jako właściwość obiektu globalnego. To, co da błąd, to coś w styluif (someUndeclaredVariable) {/* Do stuff*/}
Tim Down

2

JavaScript, jak ustawić zmienną niezdefiniowaną w wierszu poleceń:

Ustaw zmienną na niezdefiniowaną w jsterminalu linii poleceń javascript, który jest dostarczany z Javą w Ubuntu 12.10.

el@defiant ~ $ js

js> typeof boo
"undefined"

js> boo
typein:2: ReferenceError: boo is not defined

js> boo=5
5

js> typeof boo
"number"

js> delete(boo)
true

js> typeof boo
"undefined"

js> boo
typein:7: ReferenceError: boo is not defined

Jeśli ustawisz zmienną na niezdefiniowaną w javascript:

Umieść to w myjs.html:

<html>
<body>
    <script type="text/JavaScript">
        document.write("aliens: " + aliens);
        document.write("typeof aliens: " + (typeof aliens));
        var aliens = "scramble the nimitz";
        document.write("found some aliens: " + (typeof aliens));
        document.write("not sayings its aliens but... " + aliens);
        aliens = undefined;
        document.write("aliens deleted");
        document.write("typeof aliens: " + (typeof aliens));
        document.write("you sure they are gone? " + aliens);
    </script>
</body>
</html>

Drukuje to:

aliens: undefined
typeof aliens: undefined
found some aliens: string
not sayings its aliens but... scramble the nimitz
aliens deleted
typeof aliens: undefined
you sure they are gone? undefined

OSTRZEŻENIE! Ustawiając zmienną na niezdefiniowaną, ustawiasz zmienną na inną zmienną. Jeśli jakaś podstępna osoba biegnie, undefined = 'rm -rf /';to ilekroć ustawisz zmienną na niezdefiniowaną, otrzymasz tę wartość.

Być może zastanawiasz się, w jaki sposób mogę wyprowadzić obcych o nieokreślonej wartości na początku i nadal działać. Jest to spowodowane podnoszeniem skryptów javascript: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html



0

For if (something)i if (!something)jest powszechnie używane do sprawdzania, czy coś jest zdefiniowane czy nie zdefiniowane. Na przykład:

if (document.getElementById)

Identyfikator jest konwertowany na wartość logiczną, więc undefinedjest interpretowany jako false. Istnieją oczywiście inne wartości (takie jak 0 i „”), które również są interpretowane jako false, ale albo identyfikator nie powinien rozsądnie mieć takiej wartości, albo jesteś zadowolony z traktowania takiej wartości tak samo, jak niezdefiniowana.

JavaScript ma deleteoperator, którego można użyć do usunięcia członka obiektu. W zależności od zakresu zmiennej (tj. Czy jest ona globalna czy nie), możesz ją usunąć, aby stała się niezdefiniowana.

Nie ma undefinedsłowa kluczowego, którego można by użyć jako niezdefiniowanego literału. Możesz pominąć parametry w wywołaniu funkcji, aby uczynić je niezdefiniowanymi, ale można tego użyć tylko poprzez przesłanie mniejszej liczby parametrów do funkcji, nie można pominąć parametru w środku.


0

Dla zabawy, oto dość bezpieczny sposób przypisywania zmiennej „nieprzypisany”. Aby doszło do kolizji, ktoś musiałby dodać do prototypu obiektu o dokładnie takiej samej nazwie jak losowo wygenerowany ciąg. Jestem pewien, że generator losowych ciągów mógłby zostać ulepszony, ale właśnie wziąłem jeden z tego pytania: Wygeneruj losowy ciąg / znaki w JavaScript

Działa to poprzez utworzenie nowego obiektu i próbę uzyskania dostępu do właściwości z losowo wygenerowaną nazwą, która, jak zakładamy, nie będzie istnieć, a zatem będzie miała wartość niezdefiniowaną.

function GenerateRandomString() {
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for (var i = 0; i < 50; i++)
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text;
}

var myVar = {}[GenerateRandomString()];
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.