use - objetos javascript prototype




Detectando uma propriedade de objeto indefinida (20)

Qual é a melhor maneira de verificar se uma propriedade de objeto em JavaScript é indefinida?


' if (window.x) {} ' é um erro seguro

Muito provavelmente você quer if (window.x) . Esta verificação é segura mesmo que x não tenha sido declarado ( var x; ) - o navegador não lança um erro.

Exemplo: quero saber se meu navegador suporta a API de histórico

if (window.history) {
    history.call_some_function();
}

Como isso funciona:

window é um objeto que contém todas as variáveis ​​globais como seus membros, e é legal tentar acessar um membro não existente. Se x não foi declarado ou não foi definido, window.x retorna indefinido . indefinido leva a falso quando if () o avalia.


A questão resume-se a três casos:

  1. O objeto tem a propriedade e seu valor não é undefined .
  2. O objeto tem a propriedade e seu valor é undefined .
  3. O objeto não possui a propriedade.

Isso nos diz algo que considero importante:

Há uma diferença entre um membro indefinido e um membro definido com um valor indefinido.

Mas, infelizmente, o typeof obj.foo não nos diz qual dos três casos que temos. No entanto, podemos combinar isso com "foo" in obj para distinguir os casos.

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

Vale a pena notar que estes testes são os mesmos para entradas null também

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

Eu diria que, em alguns casos, faz mais sentido (e é mais claro) verificar se a propriedade está lá, do que verificar se ela está indefinida, e o único caso em que essa verificação será diferente é o caso 2, o caso raro de uma entrada real no objeto com um valor indefinido.

Por exemplo: Acabei de refatorar um monte de código que tinha um monte de verificações se um objeto tinha uma determinada propriedade.

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

Qual foi mais claro quando escrito sem um cheque para indefinido.

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

Mas, como foi mencionado, estes não são exatamente os mesmos (mas são mais do que suficientes para as minhas necessidades).


Crossposting my answer from related question Como verificar se há "indefinido" em JavaScript?

Específico para esta questão, veja casos de teste com someObject.<whatever> .

Alguns cenários ilustrando os resultados das várias respostas: http://jsfiddle.net/drzaus/UVjM4/

(Observe que o uso de var in testes faz diferença quando em um wrapper com escopo)

Código para referência:

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

E resultados:

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

Em JavaScript há nulo e não está definido . Eles têm significados diferentes.

  • undefined significa que o valor da variável não foi definido; não se sabe qual é o valor.
  • null significa que o valor da variável é definido e definido como nulo (não tem valor).

Marijn Haverbeke afirma, em seu livro on-line gratuito " Eloquent JavaScript " (ênfase minha):

Há também um valor similar, null, cujo significado é 'esse valor é definido, mas não possui um valor'. A diferença de significado entre indefinido e nulo é principalmente acadêmica e geralmente não é muito interessante. Em programas práticos, muitas vezes é necessário verificar se algo 'tem valor'. Nestes casos, a expressão algo == indefinido pode ser usada, porque, mesmo que eles não sejam exatamente o mesmo valor, null == undefined produzirá true.

Então, eu acho que a melhor maneira de verificar se algo estava indefinido seria:

if (something == undefined)

Espero que isto ajude!

Edit: Em resposta à sua edição, as propriedades do objeto devem funcionar da mesma maneira.

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

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

Eu não tenho certeza de onde a origem de usar === com typeof veio, e como uma convenção eu vejo isso usado em muitas bibliotecas, mas o operador typeof retorna uma string literal, e nós sabemos disso na frente, então por que você também quer digitar verificá-lo também?

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

Eu não vi (espero não ter perdido) alguém verificando o objeto antes da propriedade. Então, isso é o mais curto e mais eficaz (embora não necessariamente o mais claro):

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

Se obj ou obj.prop estiver indefinido, nulo ou "falso", a instrução if não executará o bloco de códigos. Este é geralmente o comportamento desejado na maioria das instruções de bloco de código (em JavaScript).


O que isso significa: "propriedade de objeto indefinida" ?

Na verdade, isso pode significar duas coisas bem diferentes! Primeiro, pode significar a propriedade que nunca foi definida no objeto e, segundo, pode significar a propriedade que possui um valor indefinido . Vamos ver este código:

var o = { a: undefined }

É oa indefinido? Sim! Seu valor é indefinido. É ob indefinido? Certo! Não há propriedade 'b' em tudo! OK, veja agora como diferentes abordagens se comportam em ambas as situações:

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

Podemos ver claramente que typeof obj.prop == 'undefined' e obj.prop === undefined são equivalentes e não distinguem essas diferentes situações. E 'prop' in obj pode detectar a situação quando uma propriedade não foi definida e não presta atenção ao valor da propriedade que pode ser indefinido.

Então o que fazer?

1) Você quer saber se uma propriedade é indefinida pelo primeiro ou segundo significado (a situação mais típica).

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

2) Você quer apenas saber se o objeto tem alguma propriedade e não se importa com o seu valor.

'prop' in obj

Notas:

  • Você não pode verificar um objeto e sua propriedade ao mesmo tempo. Por exemplo, este xa === undefined ou este typeof xa == 'undefined' gera ReferenceError: x is not defined se x não estiver definido.
  • Variável undefined é uma variável global (então, na verdade, é window.undefined nos navegadores). Ele tem sido suportado desde a primeira edição do ECMAScript e, como o ECMAScript 5, é somente leitura . Portanto, em navegadores modernos, não pode ser redefinido como verdadeiro, como muitos autores adoram nos assustar, mas isso ainda é verdade para navegadores mais antigos.

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

Vantagens de obj.prop === undefined :

  • É um pouco mais curto e parece um pouco mais bonito
  • O mecanismo de JavaScript fornecerá um erro se você tiver digitado incorretamente

Minuses de obj.prop === undefined :

  • undefined pode ser substituído em navegadores antigos

Vantagens do typeof obj.prop == 'undefined' :

  • É realmente universal! Funciona em navegadores novos e antigos.

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

  • 'undefned' ( escrito incorretamente ) aqui é apenas uma constante de string, então o mecanismo de JavaScript não pode ajudá-lo se você tiver digitado errado como acabei de fazer.

Atualização (para JavaScript do lado do servidor):

O Node.js suporta a variável global undefined como global.undefined (também pode ser usada sem o prefixo 'global'). Eu não sei sobre outras implementações de JavaScript do lado do servidor.


Se você fizer

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

ele falhará quando a variável myvar não existir, porque myvar não está definido, então o script está quebrado e o teste não tem efeito.

Como o objeto window possui um escopo global (objeto padrão) fora de uma função, uma declaração será 'anexada' ao objeto window.

Por exemplo:

var myvar = 'test';

A variável global myvar é a mesma que window.myvar ou window ['myvar']

Para evitar erros para testar quando existe uma variável global, é melhor você usar:

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

A questão se realmente existe uma variável não importa, seu valor está incorreto. Caso contrário, é bobagem inicializar as variáveis ​​com undefined, e é melhor usar o valor false para inicializar. Quando você sabe que todas as variáveis ​​que você declara são inicializadas com false, você pode simplesmente verificar seu tipo ou confiar em !window.myvar para verificar se ele possui um valor válido. Portanto, mesmo quando a variável não está definida, então !window.myvar é o mesmo para myvar = undefined ou myvar = false ou myvar = 0 .

Quando você espera um tipo específico, teste o tipo da variável. Para acelerar o teste de uma condição, é melhor você fazer:

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

Quando a primeira e simples condição é verdadeira, o intérprete pula os próximos testes.

É sempre melhor usar a instância / objeto da variável para verificar se ela tem um valor válido. É mais estável e é uma maneira melhor de programar.

(y)


Usar:

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

Se uma variável de objeto que tem algumas propriedades você pode usar a mesma coisa assim:

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

Aqui está a minha situação:

Eu estou usando o resultado de uma chamada REST. O resultado deve ser analisado do JSON para um objeto JavaScript.

Há um erro que preciso defender. Se os argumentos para a chamada de descanso estiverem incorretos, desde que o usuário especifique os argumentos errados, a chamada de retorno volta basicamente vazia.

Ao usar este post para me ajudar a defender contra isso, eu tentei isso.

if( typeof restResult.data[0] === "undefined" ) { throw  "Some error"; }

Para minha situação, se restResult.data [0] === "object", posso começar a inspecionar com segurança o resto dos membros. Se indefinido, em seguida, jogue o erro como acima.

O que estou dizendo é que, para minha situação, todas as sugestões acima neste post não funcionaram. Não estou dizendo que estou certo e todo mundo está errado. Eu não sou um mestre em JavaScript, mas espero que isso ajude alguém.


Percorrendo os comentários, para quem quiser conferir ambos é indefinido ou seu valor é nulo:

//Just in JavaScript
var s; // Undefined
if (typeof s == "undefined" || s === null){
    alert('either it is undefined or value is null')
}

Se você estiver usando a biblioteca jQuery, jQuery.isEmptyObject()será suficiente para ambos os casos,

var s; // Undefined
jQuery.isEmptyObject(s); // Will return true;

s = null; // Defined as null
jQuery.isEmptyObject(s); // Will return true;

//Usage
if (jQuery.isEmptyObject(s)) {
    alert('Either variable:s is undefined or its value is null');
} else {
     alert('variable:s has value ' + s);
}

s = 'something'; // Defined with some value
jQuery.isEmptyObject(s); // Will return false;

Se você estiver usando Angular:

angular.isUndefined(obj)
angular.isUndefined(obj.prop)

Underscore.js:

_.isUndefined(obj) 
_.isUndefined(obj.prop) 

Você pode obter um array todo indefinido com path usando o seguinte código.

 function getAllUndefined(object) {

        function convertPath(arr, key) {
            var path = "";
            for (var i = 1; i < arr.length; i++) {

                path += arr[i] + "->";
            }
            path += key;
            return path;
        }


        var stack = [];
        var saveUndefined= [];
        function getUndefiend(obj, key) {

            var t = typeof obj;
            switch (t) {
                case "object":
                    if (t === null) {
                        return false;
                    }
                    break;
                case "string":
                case "number":
                case "boolean":
                case "null":
                    return false;
                default:
                    return true;
            }
            stack.push(key);
            for (k in obj) {
                if (obj.hasOwnProperty(k)) {
                    v = getUndefiend(obj[k], k);
                    if (v) {
                        saveUndefined.push(convertPath(stack, k));
                    }
                }
            }
            stack.pop();

        }

        getUndefiend({
            "": object
        }, "");
        return saveUndefined;
    }

jsFiddle link


A solução está incorreta. Em JavaScript,

null == undefined

retornará true, porque ambos são "convertidos" para um booleano e são falsos. A maneira correta seria verificar

if (something === undefined)

qual é o operador de identidade ...


Estou surpreso por ainda não ter visto essa sugestão, mas é ainda mais específico do que testar typeof. Use Object.getOwnPropertyDescriptor()se você precisar saber se uma propriedade de objeto foi inicializada com undefinedou se nunca foi inicializada:

// to test someObject.someProperty
var descriptor = Object.getOwnPropertyDescriptor(someObject, 'someProperty');

if (typeof descriptor === 'undefined') {
  // was never initialized
} else if (typeof descriptor.value === 'undefined') {
  if (descriptor.get || descriptor.set) {
    // is an accessor property, defined via getter and setter
  } else {
    // is initialized with `undefined`
  }
} else {
  // is initialized with some other value
}

Eu uso if (this.variable)para testar se está definido. Simples if (variable), recomendado acima , falha para mim. Acontece que ele funciona apenas quando a variável é um campo de algum objeto, obj.someFieldpara verificar se ele está definido no dicionário. Mas podemos usar thisou windowcomo o objeto do dicionário, uma vez que qualquer variável é um campo na janela atual, como eu a entendo. Portanto, aqui está um teste

if (this.abc) alert("defined"); else alert("undefined");

abc = "abc";
if (this.abc) alert("defined"); else alert("undefined");

Ele primeiro detecta que a variável abcé indefinida e é definida após a inicialização.


Lendo por isso, eu estou espantado por não ter visto isso. Eu encontrei vários algoritmos que funcionariam para isso.

Nunca definido

Se o valor de um objeto nunca foi definido, isso impedirá o retorno truese ele for definido como nullou undefined. Isso é útil se você quiser que o verdadeiro seja retornado para valores definidos comoundefined

if(obj.prop === void 0) console.log("The value has never been defined");

Definido como indefinido ou nunca definido

Se você quer que isso resulte como truevalores definidos com o valor de undefined, ou nunca definido, você pode simplesmente usar=== undefined

if(obj.prop === undefined) console.log("The value is defined as undefined, or never defined");

Definido como um valor falso, indefinido, nulo ou nunca definido.

Comumente, as pessoas me pediram um algoritmo para descobrir se um valor é falso undefinedou null. Os seguintes trabalhos.

if(obj.prop == false || obj.prop === null || obj.prop === undefined) {
    console.log("The value is falsy, null, or undefined");
}

Simplesmente qualquer coisa não é definida em JavaScript, é indefinida , não importa se é uma propriedade dentro de um Object / Array ou apenas como uma simples variável ...

JavaScript tem o typeofque torna muito fácil detectar uma variável indefinida.

Simplesmente verifique se typeof whatever === 'undefined'e ele retornará um booleano.

É assim que a famosa função isUndefined()do AngularJs v.1x está escrita:

function isUndefined(value) {return typeof value === 'undefined';} 

Então, como você vê a função receber um valor, se esse valor for definido, ele retornará false, caso contrário, para valores indefinidos, retorne true.

Então vamos dar uma olhada em quais serão os resultados quando passarmos valores, incluindo propriedades de objetos como abaixo, esta é a lista de variáveis ​​que temos:

var  = {};
.javascipt = 'javascript';
var today;
var self = this;
var num = 8;
var list = [1, 2, 3, 4, 5];
var y = null;

e nós verificamos como abaixo, você pode ver os resultados na frente deles como um comentário:

isUndefined(); //false
isUndefined(.javascipt); //false
isUndefined(today); //true
isUndefined(self); //false
isUndefined(num); //false
isUndefined(list); //false
isUndefined(y); //false
isUndefined(.java); //true
isUndefined(.php); //true
isUndefined( && .css); //true

Como você pode ver, podemos verificar qualquer coisa com o uso de algo assim em nosso código, como mencionado, você pode simplesmente usar typeof em seu código, mas se você usá-lo várias vezes, crie uma função como a amostra angular que eu compartilho e reutilizo como seguindo o padrão de código DRY.

Também mais uma coisa, para verificar a propriedade em um objeto no aplicativo real que você não tem certeza se o objeto existe ou não, verifique se o objeto existe primeiro.

Se você verificar uma propriedade em um objeto e o objeto não existir, isso gerará um erro e interromperá a execução do aplicativo inteiro.

isUndefined(x.css);
VM808:2 Uncaught ReferenceError: x is not defined(…)

Tão simples que você pode embrulhar dentro de uma declaração if como abaixo:

if(typeof x !== 'undefined') {
  //do something
}

Que também é igual a isDefined em Angular 1.x ...

function isDefined(value) {return typeof value !== 'undefined';}

Também outras estruturas de javascript como sublinhado tem verificação de definição semelhante, mas eu recomendo que você use typeofse você já não estiver usando nenhuma estrutura.

Eu também adiciono esta seção do MDN que possui informações úteis sobre typeof, undefined e void (0).

Igualdade restrita e indefinida
Você pode usar os operadores de igualdade e desigualdade estritos para determinar se uma variável tem um valor. No código a seguir, a variável x não está definida e a instrução if é avaliada como verdadeira.

var x;
if (x === undefined) {
   // these statements execute
}
else {
   // these statements do not execute
}

Nota: O operador de igualdade estrita em vez do operador de igualdade padrão deve ser usado aqui, porque x == undefined também verifica se x é nulo, enquanto que a igualdade estrita não é. null não é equivalente a indefinido. Veja operadores de comparação para detalhes.

Tipo de operador e indefinido
Alternativamente, typeof pode ser usado:

var x;
if (typeof x === 'undefined') {
   // these statements execute
}

Uma razão para usar o typeof é que ele não lança um erro se a variável não foi declarada.

// x has not been declared before
if (typeof x === 'undefined') { // evaluates to true without errors
   // these statements execute
}

if (x === undefined) { // throws a ReferenceError

}

No entanto, esse tipo de técnica deve ser evitado. JavaScript é uma linguagem com escopo estatístico, portanto, saber se uma variável é declarada pode ser lido, verificando se ela está declarada em um contexto delimitador. A única exceção é o escopo global, mas o escopo global está vinculado ao objeto global, portanto, verificar a existência de uma variável no contexto global pode ser feito verificando a existência de uma propriedade no objeto global (usando o operador in, por exemplo).

Operador vazio e indefinido

O operador nulo é uma terceira alternativa.

var x;
if (x === void 0) {
   // these statements execute
}

// y has not been declared before
if (y === void 0) {
   // throws a ReferenceError (in contrast to `typeof`)
}

mais> here


"propertyName" in obj //-> true | false

function isUnset(inp) {
  return (typeof inp === 'undefined')
}

Retorna false se a variável for definida e true se for indefinida.

Então use:

if (isUnset(var)) {
  // initialize variable here
}




undefined