0

だから私はここでほとんどの質問を通り抜けてきました。また、かなりの数の記事が良い点と悪い点があります。

私がいくつかの追加の説明を探しているのは、未定義および未宣言の変数がどのように扱われるかです。

以下のコードを取ります。

var a;

if(a == null) // True - Due to Type Coercion

if(a == 'null') // False

if(a === null) // False

if(a === 'null') // False

if(a == undefined) // True

if(a === undefined) // True

if(a == 'undefined') // False

if(a === 'undefined') // False

if(a) // False - A is undefined

alert(typeof(a)) // undefined

上記のすべてを理解しています。しかし、宣言されていない変数を見ると、物事は奇妙になります。特に「varb;」を省略していることに注意してください。

 alert(typeof(b)) // undefined

 if(typeof(b) == 'undefined') // True

 if(typeof(b) === 'undefined') // True - This tells me the function typeof is returning a string value

 if(typeof(b) == 'null') // False

 if(typeof(b) === 'null') // False

 if(typeof(b) == null) // False

 if(typeof(b) === null) // False

 if(b) // Runtime Error - B is undefined

それ以外の操作を行うと、typeof(b)によってランタイムエラーが発生します。それでも、言語が式を評価する方法の背後にある論理を理解することができます。

だから今私はaの存在しないプロパティを見て、本当に混乱しています。

if(a.c) // Runtime Error - c is null or not an object
alert(typeof(a.c)) // Runtime Error - undefined is null or not an object

この場合のcは、前の例のbのように扱われると思いますが、そうではありません。実際にaを何かに初期化する必要があります。そうすれば、bと同じように動作させることができます。そして、ランタイムエラーをスローしないようにします。

なぜそうなのですか?未定義の型の特別な処理がありますか、それともtypeof関数が実行時エラーをスローしているサブプロパティを評価するために再帰的に何かを実行していますか?

  1. ここでの実際的な質問は、acでネストされたオブジェクトcをチェックしている場合、aが未定義の場合、cは未定義であるとすぐに想定できるということだと思います。

  2. そして、MyObject.Something.Something.Something.xでxのように設定されているかどうかを確認するために、極端にネストされたオブジェクトをチェックしたい場合、最善の方法は何ですか?チェーンの次の構造に進む前に、各要素が存在することを確認して、要素ごとに構造をナビゲートする必要がありますか?

4

7 に答える 7

2

aが未定義の場合、cは未定義であるとすぐに推測できますか?

はい。

チャニンの次の構造に移動する前に、各要素が存在することを確認して、要素ごとに構造をナビゲートする必要がありますか?

はい。

于 2009-12-01T18:59:41.700 に答える
1

理由

alert(typeof(a.c))

実行時エラーが発生し、

alert(typeof(b))

最初の例では、未定義のオブジェクトのプロパティにアクセスしようとしているわけではありません。これにより、結果をにフィードする前にランタイムエラーが発生します。typeof()

于 2009-12-01T19:04:02.830 に答える
1

undefinedこれはグローバル変数(!)であり、あなた(または他の誰か)がそれに値を割り当てることができることを忘れないでください。そのため、ここでの例は間違っている可能性があります。

if(a == undefined) // True

if(a === undefined) // True

本当に未定義が必要な場合は、それの独自の「コピー」を取得できます

var local_undefined;
于 2009-12-01T19:22:04.960 に答える
0

通常、親のいずれかが存在する可能性のある極端に(3レベルを超える)ネストされたオブジェクトをテストする必要性に遭遇することはありません。したがって、テストする必要がある場合は、次のように記述します。undefined

if( typeof(a) != 'undefined' && a.c ) {
   // Do something won't run because a is undefined
}

var a = {};

if( typeof(a) != 'undefined' && a.c ) {
   // Do something won't run because though a is defined,
   // a.c is undefined. This expression tests to see if a.c evaluates
   // to true, but won't throw an error even if it is 
   // undefined.
}

a.cいつでも含むことができる0false、それでもテストに合格する必要がある場合は、完全なテストを使用してくださいtypeof

var a = {};
a.c = false;

if( typeof(a) != 'undefined' && typeof(a.c) != 'undefined' ) {
   // Do something will run because though both a and a.c are defined.
}
于 2009-12-01T19:03:16.060 に答える
0

JavaScriptは、値undefined(もtypeof a === "undefined")が値が与えられるまで変数が持つものであるという点で奇妙です。nullとは異なる明確な値ですundefined。JavaScriptの型システムは緩いため、変数の値を比較およびテストするときに発生する暗黙の型強制があります。

変数が宣言されていない場合、エラーなしでそれを参照することはできませんが、typeof演算子を使用してテストすることはできます(その結果は文字列になります"undefined")。宣言されているが割り当てられていない変数は参照できますが、値は含まれていますundefined。オブジェクトの未定義のプロパティはいつでも参照でき、割り当てられていない場合は、値がになりますundefined

JavaScript型の強制と、空と見なすのに役立つことが多いさまざまな値について詳しく説明したので、この回答も参照してください。

VBScriptのIsEmptyにはJavaScriptで同等のものがありますか?

  1. ネストされたオブジェクトをテストするときに、親がundefined(またはnull)の場合、子はないため、それ以上のテストは必要ありません。

  2. 高度にネストされたオブジェクトを安全にテストするには、を使用して最上位の親をテストする必要がありtypeofますが、実際の値について子をテストできます(空の回答のテストを参照)。これは、トップレベルが宣言されていない可能性があるためですが、オブジェクトの未定義のプロパティはいつでも参照できます。

于 2009-12-01T19:04:23.717 に答える
0

深くネストされた子の場合

try{ if(a.b.c.d.e) {
    // do your stuff
}}catch(e){}

try-catchルートは、よりエレガントで、タイプコーディングがはるかに少ないソリューションです。

そして、ここに例があります:

grand=""
a={ b:{ c:{ d:{ e:"Hello Ancestor" } } } }

try{ if(a.b.c.d.e) {
    grand = a.b.c.d.e
}}catch(e){}

alert( grand )

退屈なタイプの方法を見てください。

if(typeof a === undefined) {
    if(typeof a.b === undefined) {
        if(typeof a.b.c === undefined) {
            if(typeof a.b.c.d === undefined) {
                if(typeof a.b.c.d.e === undefined) {
                    // your stuff
                }
            }
        }
    }
}

try-catchブロックを関数にラップした後は、さらに洗練された理想的なソリューションになる可能性がありますが、関数に「文字列」として渡すことができる参照変数名を変数の内容に置き換える方法は知られていません。たとえば、次のことはできません。

function isDefined(v) {
    if (typeof valueOfVar(v) !== undefined)
        return true
    else
        return false
}
alert( isDefined('a.b.c.d.e') ) // must be passed as a string to avoid runtime error

JavaScriptにはvalueOfVar()は存在しません。これは単なる例です。


しかし、何を推測するか、私は悟り、邪悪な解決策を得ました:)

// a={ b:{ c:{ d:{ e:0 } } } }

function exist(v) {
    var local_undefined
    try{ if( eval(v) !== local_undefined ) {
        return true
    }}catch(e){}
    return false
}
alert( exist('a.b.c.d.e') )
于 2013-07-20T12:10:44.267 に答える
0

presents()関数の重要な更新—exists()を利用する2つの追加関数

これらは、JavaScriptでランタイムエラーを発生させることなく任意のネストレベルの変数/プロパティ/オブジェクト定義/空/宣言されていないかどうかをテストするために必要なすべてをカバーします

function exists (v) {
    var local_undefined;
    try{ if( eval(v) !== local_undefined ) {
        return true
    }}catch(e){}
    return false
}

function empty (v) {
    if (exists(v)) {
        v = eval(v);
        if (typeof v == 'object') {
            return Object.keys(v).length === 0
        } else if (v)
            return false
    }
    return true
}

function value (v) {
    var local_undefined;
    if (exists(v))
        return eval(v)
    return local_undefined
}


/////////////////////////////////////////
// TEST

ref = 'a.b.c.d.e';

alert( ref +' : '+ value(ref) + '\n'
        + '\nexists\t' + exists(ref)
        + '\nempty\t' + empty(ref)
        + '\nvalue\t' + value(ref)
    );

a = { b:{ c:{ d:{ e:"Hello Ancestor" } } } };
alert( ref +' : '+ value(ref) + '\n'
        + '\nexists\t' + exists(ref)
        + '\nempty\t' + empty(ref)
        + '\nvalue\t' + value(ref)
    )

a = { b:{ c:{ d:{ e:0 } } } };
alert( ref +' : '+ value(ref) + '\n'
        + '\nexists\t' + exists(ref)
        + '\nempty\t' + empty(ref)
        + '\nvalue\t' + value(ref)
    );

b='a'; obj={a:5}; ref='obj[b]';
alert( ref +' : '+ value(ref) + '\n'
        + '\nexists\t' + exists(ref)
        + '\nempty\t' + empty(ref)
        + '\nvalue\t' + value(ref)
    );

ただし、これらのメソッドは、exists() empty() value()関数がこれらの変数にアクセスできる場合、つまり関数と変数の両方が同じスコープで定義されている場合にのみ機能します。

これは、ローカル関数変数もテストできるようにするために必要です。そうしないと、で宣言されたローカル関数変数が呼び出された関数varに含まれることになります。undefinedexists() empty() value()

を含めずに関数のローカル変数をテストするexists() empty() value()には、try/catchその関数内でブロックを使用する必要があります


ローカル関数変数をテストするための代替の邪悪な解決策は次のとおりです。これらのコードスニペットはグローバルスコープで定義してからeval()で呼び出すことができます。

is_ = "v_='"
var_ = "v_='"
get_ = "v_='"
set_ = "v_='"

_exists = "';\nvar local_undefined;\n"
        + "try{ if( eval(v_) === local_undefined ) false; else true }\n"
        + "catch(e){false}\n"

_empty = "';\nif ( eval(\"'\"+_exists) ) {\n"
        + " v_ = eval(v_);\n"
        + " if (typeof v_ == 'object') {\n"
        + "     Object.keys(v_).length === 0;\n"
        + " }\n\telse if (v_)\n"
        + "     false;\n"
        + " else true\n"
        + "} else true"

_value = "';\nif ( eval(\"'\"+_exists) )\n"
    + " eval(v_);\n"
    + "else local_undefined"

_valOrEmpty = "';\n( eval(\"'\"+_exists) )\n"
    + " ? eval(\"'\"+_value) : ''"

_valOrDefault_ = "';\n( eval(\"'\"+_exists) )\n"
    + " ? eval(\"'\"+_value) : "

function f() {
    var a = { b:{ c:{ d:{ e:"Hello Ancestor" } } } };
    ref = 'a.b.c.d.e'
    alert( ref+'\n'   
        +'\nexists\t\t'     + eval(is_  +ref+ _exists)
        +'\nempty\t\t'      + eval(is_  +ref+ _empty)
        +'\nvalue\t\t'      + eval(get_ +ref+ _value)
        +'\n'
        +'\nvalOrEmpty\t'   + eval(get_ +ref+ _valOrEmpty)
        +'\nvalOrDefault\t' + eval(get_ +ref+ _valOrDefault_ +'"Default Value"')
        )
}

d=""; while (d.length < 20) d="—"+d; d="\n\n// "+d+"\n// "
jsCode  ='// ( is_  +var+ _exists )\n\n'                + is_ +'a.b.c.d.e'+_exists
        +d+' ( is_  +var+ _empty )\n\n'                 + is_ +'a.b.c.d.e'+_empty
        +d+' ( get_ +var+ _value )\n\n'                 + get_+'a.b.c.d.e'+_value
        +d+' ( get_ +var+ _valOrEmpty )\n\n'            + var_+'a.b.c.d.e'+_valOrEmpty
        +d+' ( get_ +var+ _valOrDefault_ default )\n\n' + var_+'a.b.c.d.e'+_valOrDefault_+"'Default Value'"

alert(jsCode)

f()
// even though that looks ugly, this is the tidiest solution
// to the awkward 17-year old JavaScript error-handling

これを賢く使う

if ( eval(is_  +'any.var.or.property.from.local.or.global.scope'+ _exists) ) {
    // do your stuff
}
于 2013-07-20T13:24:51.440 に答える