Вопрос: Обнаружение свойства неопределенного объекта


Каков наилучший способ проверить, не определено ли свойство объекта в JavaScript?


2408


источник


Ответы:


Использование:

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

Если переменная объекта, обладающая некоторыми свойствами, вы можете использовать одно и то же:

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

Поскольку ECMAScript 5, undefinedне могут быть перезаписаны, поэтому my_obj === undefinedбудет работать, но только если my_objсуществует. Это может быть или не быть желательным, потому что вы можете также использовать nullесли вам нужна эта семантика (см. В чем разница между null и undefined в JavaScript? ). Однако для свойств объекта он работает независимо от того, существует ли свойство.


2296



Я считаю, что есть ряд неправильных ответов на эту тему. Вопреки распространенному мнению, «неопределенный» не ключевое слово в JavaScript и на самом деле может иметь присвоенное ему значение.

Правильный код

Самый надежный способ выполнить этот тест:

if (typeof myVar === "undefined")

Это всегда возвращает правильный результат и даже обрабатывает ситуацию, когда myVarне объявляется.

Вырожденный код. НЕ ИСПОЛЬЗУЙ.

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

Дополнительно, myVar === undefinedвызовет ошибку в ситуации, когда myVar не объявлен.


801



В JavaScript есть ноль и есть не определено , Они имеют разные значения.

  • не определено означает, что значение переменной не определено; неизвестно, что это за значение.
  • ноль означает, что значение переменной определено и установлено в значение null (не имеет значения).

В своей бесплатной онлайн-книге Марин Хавербеке заявляет, Красноречивый JavaScript »(внимание мое):

Существует также аналогичное значение, null, значение которого «это значение определено, но оно не имеет значения». Разница в значении между неопределенным и нулевым является в основном академической и обычно не очень интересной. В практических программах часто необходимо проверить, имеет ли что-то «значение». В этих случаях может использоваться выражение something == undefined, потому что, хотя они не являются точно таким же значением, null == undefined будет выдавать true.

Итак, я думаю, лучший способ проверить, было ли что-то неопределенным:

if (something == undefined)

Надеюсь это поможет!

Редактировать: В ответ на ваше редактирование свойства объекта должны работать одинаково.

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

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

133



Несмотря на то, что я настоятельно рекомендовал многие другие ответы здесь, typeof это плохой выбор , Он никогда не должен использоваться для проверки того, имеют ли переменные значение undefined, поскольку он действует как комбинированная проверка стоимости undefinedи существует ли переменная. В подавляющем большинстве случаев вы знаете, когда существует переменная, и typeofпросто представит потенциал для бесшумного сбоя, если вы сделаете опечатку в имени переменной или в строковом литерале '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!
}

Поэтому, если вы не используете функцию обнаружения признаков2, где есть неопределенность в отношении того, будет ли данное имя областью видимости (например, проверка typeof module !== 'undefined'как шаг в коде, специфичном для среды CommonJS), typeofявляется вредным выбором при использовании в переменной, и правильным вариантом является сравнение значения напрямую:

var foo = …;

if (foo === undefined) {
    ⋮
}

Некоторые распространенные заблуждения об этом включают:

  • что чтение «неинициализированной» переменной ( var foo) или параметр ( function bar(foo) { … }, называемый bar()) не удастся. Это просто неверно: переменные без явной инициализации и параметры, которые не были заданы, всегда становятся undefined, и всегда находятся в сфере охвата.

  • что undefinedмогут быть перезаписаны. Это намного больше. undefinedне является ключевым словом в JavaScript. Вместо этого это свойство для глобального объекта с неопределенным значением. Однако, поскольку ES5, это свойство было только для чтения а также неперестраиваемый , Ни один современный браузер не позволит undefinedимущество, которое необходимо изменить, и с 2017 года это имело место в течение длительного времени. Отсутствие строгого режима не влияет undefinedПоведение - это просто делает такие заявления, как undefined = 5ничего не делать, а не бросать. Однако, поскольку это не ключевое слово, вы можете объявлять переменные с именем undefined, и эти переменные могут быть изменены, что делает этот раз-общий шаблон:

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

    Больше опасны, чем использование глобального undefined, Если вы должны быть совместимы с ES3, замените undefinedс void 0- не прибегать к typeof, ( voidвсегда был унарным оператором, который оценивает значение Undefined для любого операнда.)

С тем, как переменные работают в стороне, пришло время обратиться к актуальному вопросу: свойства объекта. Нет никакой причины когда-либо использовать typeofдля свойств объекта. Предыдущее исключение в отношении обнаружения функции здесь не применяется - typeofтолько имеет особое поведение для переменных, а выражения, которые ссылаются на свойства объекта, не являются переменными.

Эта:

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

является всегда точно эквивалент к этому:

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

и принимая во внимание приведенный выше совет, чтобы не путать читателей о том, почему вы используете typeof, поскольку имеет смысл использовать ===чтобы проверить на равенство, потому что он может быть реорганизован для проверки значения переменной позже и потому, что он просто выглядит лучше, вы всегда должны использовать === undefined³ здесь также ,

Что-то еще, чтобы рассмотреть, когда дело доходит до свойств объекта, действительно ли вы хотите проверить undefinedвообще. Указанное имя свойства может отсутствовать на объекте (создавая значение undefinedпри чтении), присутствующих на самом объекте со значением undefined, присутствующих на прототипе объекта со значением undefined, или присутствовать на любом из тех, undefinedстоимость. 'key' in objскажет вам, находится ли ключ в цепочке прототипов объекта, и Object.prototype.hasOwnProperty.call(obj, 'key')расскажет вам, находится ли он непосредственно на объекте. Я не буду вдаваться в подробности в этом ответе о прототипах и использовать объекты в виде строковых карт, хотя, поскольку он в основном предназначен для противодействия всем плохим советам в других ответах, независимо от возможных интерпретаций исходного вопроса. Следить за публикациями объектные прототипы на MDN для большего!

¹ необычный выбор имени переменной? это настоящий мертвый код из расширения NoScript для Firefox.
² не предполагают, что не зная, что в сфере охвата, в общем, все в порядке. бонусная уязвимость, вызванная злоупотреблением динамической областью: Project Zero 1225
³ в очередной раз предполагает среду ES5 + и что undefinedотносится к undefinedсвойство глобального объекта. замена void 0в противном случае.


127



What does this mean: "undefined object property"?

Actually it can mean two quite different things! First, it can mean the property that has never been defined in the object and, second, it can mean the property that has an undefined value. Let's look at this code:

var o = { a: undefined }

Is o.a undefined? Yes! Its value is undefined. Is o.b undefined? Sure! There is no property 'b' at all! OK, see now how different approaches behave in both situations:

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

We can clearly see that typeof obj.prop == 'undefined' and obj.prop === undefined are equivalent, and they do not distinguish those different situations. And 'prop' in obj can detect the situation when a property hasn't been defined at all and doesn't pay attention to the property value which may be undefined.

So what to do?

1) You want to know if a property is undefined by either the first or second meaning (the most typical situation).

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

2) You want to just know if object has some property and don't care about its value.

'prop' in obj

Notes:

  • You can't check an object and its property at the same time. For example, this x.a === undefined or this typeof x.a == 'undefined' raises ReferenceError: x is not defined if x is not defined.
  • Variable undefined is a global variable (so actually it is window.undefined in browsers). It has been supported since ECMAScript 1st Edition and since ECMAScript 5 it is read only. So in modern browsers it can't be redefined to true as many authors love to frighten us with, but this is still a true for older browsers.

Final fight: obj.prop === undefined vs typeof obj.prop == 'undefined'

Pluses of obj.prop === undefined:

  • It's a bit shorter and looks a bit prettier
  • The JavaScript engine will give you an error if you have misspelled undefined

Minuses of obj.prop === undefined:

  • undefined can be overridden in old browsers

Pluses of typeof obj.prop == 'undefined':

  • It is really universal! It works in new and old browsers.

Minuses of typeof obj.prop == 'undefined':

  • 'undefned' (misspelled) here is just a string constant, so the JavaScript engine can't help you if you have misspelled it like I just did.

Update (for server-side JavaScript):

Node.js supports the global variable undefined as global.undefined (it can also be used without the 'global' prefix). I don't know about other implementations of server-side JavaScript.


99



The issue boils down to three cases:

  1. The object has the property and its value is not undefined.
  2. The object has the property and its value is undefined.
  3. The object does not have the property.

This tells us something I consider important:

There is a difference between an undefined member and a defined member with an undefined value.

But unhappily typeof obj.foo does not tell us which of the three cases we have. However we can combine this with "foo" in obj to distinguish the cases.

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

Its worth noting that these tests are the same for null entries too

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

I'd argue that in some cases it makes more sense (and is clearer) to check whether the property is there, than checking whether it is undefined, and the only case where this check will be different is case 2, the rare case of an actual entry in the object with an undefined value.

For example: I've just been refactoring a bunch of code that had a bunch of checks whether an object had a given property.

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

Which was clearer when written without a check for undefined.

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

But as has been mentioned these are not exactly the same (but are more than good enough for my needs).


59



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

This worked for me while the others didn't.


38



I'm not sure where the origin of using === with typeof came from, and as a convention I see it used in many libraries, but the typeof operator returns a string literal, and we know that up front, so why would you also want to type check it too?

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



Crossposting my answer from related question How to check for "undefined" in JavaScript?

Specific to this question, see test cases with someObject.<whatever>.


Some scenarios illustrating the results of the various answers: http://jsfiddle.net/drzaus/UVjM4/

(Note that the use of var for in tests make a difference when in a scoped wrapper)

Code for reference:

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

And results:

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



I didn't see (hope I didn't miss it) anyone checking the object before the property. So, this is the shortest and most effective (though not necessarily the most clear):

if (obj && obj.prop) {
  // Do something;
}

If the obj or obj.prop is undefined, null, or "falsy", the if statement will not execute the code block. This is usually the desired behavior in most code block statements (in JavaScript).


13



If you do

if (myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

it will fail when the variable myvar does not exists, because myvar is not defined, so the script is broken and the test has no effect.

Because the window object has a global scope (default object) outside a function, a declaration will be 'attached' to the window object.

For example:

var myvar = 'test';

The global variable myvar is the same as window.myvar or window['myvar']

To avoid errors to test when a global variable exists, you better use:

if(window.myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

The question if a variable really exists doesn't matter, its value is incorrect. Otherwise, it is silly to initialize variables with undefined, and it is better use the value false to initialize. When you know that all variables that you declare are initialized with false, you can simply check its type or rely on !window.myvar to check if it has a proper/valid value. So even when the variable is not defined then !window.myvar is the same for myvar = undefined or myvar = false or myvar = 0.

When you expect a specific type, test the type of the variable. To speed up testing a condition you better do:

if( !window.myvar || typeof window.myvar != 'string' )
{
    alert('var does not exists or is not type of string');
}

When the first and simple condition is true, the interpreter skips the next tests.

It is always better to use the instance/object of the variable to check if it got a valid value. It is more stable and is a better way of programming.

(y)


13