كيفية التحقق من "غير محدد" في JavaScript؟




undefined (11)

ما هي أنسب طريقة لاختبار ما إذا كان متغير غير محدد في JavaScript؟ لقد رأيت عدة طرق ممكنة:

if (window.myVariable)

أو

if (typeof(myVariable) != "undefined")

أو

if (myVariable) //This throws an error if undefined. Should this be in Try/Catch?

أنا استخدامه كمعلمة وظيفة واستبعاده على تنفيذ وظيفة بهذه الطريقة أحصل على "حقيقية" غير معرفة. على الرغم من أنها تتطلب منك وضع الشفرة داخل إحدى الوظائف. لقد وجدت هذا أثناء قراءة مصدر jQuery.

undefined = 2;

(function (undefined) {
   console.log(undefined); // prints out undefined
   // and for comparison:
   if (undeclaredvar === undefined) console.log("it works!")
})()

بالطبع يمكنك فقط استخدام typeof رغم ذلك. ولكن كل ما عندي من الشفرات عادة ما يكون داخل دالة محتوية على أي حال ، لذا فإن استخدام هذه الطريقة ربما يوفر لي بعض البايتات هنا وهناك.


أنا شخصيا استخدم

myVar === undefined

تحذير: يرجى ملاحظة أن === يستخدم أكثر من == وأن myVar قد تم الإعلان عنه مسبقًا (لم يتم تعريفه ).

أنا لا أحب typeof myVar === "undefined" . أعتقد أنها طويلة وغير ضرورية. (يمكنني الحصول على الشيء نفسه في أقل رمز.)

الآن سيشعر بعض الناس بالألم عندما يقرؤون هذا ، يصرخ: "انتظر! WAAITTT! undefined يمكن إعادة تعريفه!"

رائع. انا اعرف هذا. ثم مرة أخرى ، يمكن إعادة تعريف معظم المتغيرات في جافا سكريبت. في حالة عدم استخدام أي معرف مضمّن يمكن إعادة تعريفه؟

إذا اتبعت هذه القاعدة ، فهذا جيد بالنسبة لك: أنت لست منافقاً.

الشيء هو ، من أجل القيام بالكثير من العمل الحقيقي في JS ، يحتاج المطورون إلى الاعتماد على معرّفات قابلة لإعادة التعريف لتكون على حقيقتهم. أنا لا أسمع الناس يقولون لي أنني لا يجب استخدام setTimeout لأن شخص ما يمكن

window.setTimeout = function () {
    alert("Got you now!");
};

خلاصة القول ، "يمكن إعادة تعريفها" الوسيطة لعدم استخدام الخام === undefined وهمية.

(إذا كنت لا تزال خائفاً من إعادة تعريفك ، فلماذا تقوم بإدماج رمز المكتبة غير المختبر بصورة عمياء في قاعدة الكود الخاص بك؟ أو حتى أبسط: أداة الفحص).

أيضا ، مثل نهج typeof ، يمكن لهذه التقنية "اكتشاف" المتغيرات غير المصرح بها:

if (window.someVar === undefined) {
    doSomething();
}

لكن كلا هذين الأسلوبين يتسربان في تجريدهما. أحثك على عدم استخدام هذا أو حتى

if (typeof myVar !== "undefined") {
    doSomething();
}

يعتبر:

var iAmUndefined;

للقبض سواء أعلن ذلك المتغير أم لا ، قد تحتاج إلى اللجوء إلى المشغل. (في كثير من الحالات ، يمكنك ببساطة قراءة التعليمات البرمجية O_o).

if ("myVar" in window) {
    doSomething();
}

لكن انتظر! هناك المزيد! ماذا لو حدث بعض سحر سلسلة النموذج ...؟ الآن حتى لا تفوق متفوقة in المشغل. (حسناً ، لقد انتهيت هنا من هذا الجزء إلا أن أقول أنه من أجل 99٪ من الوقت ، فإن === undefined (و **** السعال **** typeof ) يعمل بشكل جيد. إذا كنت تهتم حقًا ، يمكنك قرأت عن هذا الموضوع من تلقاء نفسها.)


إذا كان غير معرّف ، فلن يكون مساوياً لسلسلة تحتوي على الأحرف "غير معرفة" ، لأن السلسلة غير معرّفة.

يمكنك التحقق من نوع المتغير:

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

في بعض الأحيان لا تحتاج حتى إلى التحقق من النوع. إذا كانت قيمة المتغير لا يمكن تقييمها إلى false عند تعيينها (على سبيل المثال إذا كانت وظيفة) ، فيمكنك فقط تقييم المتغير. مثال:

if (something) {
  something(param);
}

إذا كنت مهتمًا بمعرفة ما إذا كان قد تم الإعلان عن متغير بغض النظر عن قيمته ، فإن استخدام المشغل هو الطريقة الأسلم للذهاب. خذ بعين الاعتبار هذا المثال.

// global scope
var theFu; // theFu has been declared, but its value is undefined
typeof theFu; // "undefined"

ولكن قد لا يكون هذا هو النتيجة المقصودة في بعض الحالات ، حيث تم الإعلان عن المتغير أو الخاصية ولكن لم يتم التهيئة لها. استخدم عامل التشغيل لإجراء فحص أكثر قوة.

"theFu" in window; // true
"theFoo" in window; // false

إذا كنت مهتمًا بمعرفة ما إذا كان المتغير لم يتم الإعلان عنه أو أنه لم يتم تحديد القيمة ، فاستخدم عامل التشغيل typeof .

if (typeof myVar != 'undefined')

يضمن عامل التشغيل typeof إرجاع سلسلة. المقارنات المباشرة ضد undefined هي مزعجة كما يمكن الكتابة فوق undefined .

window.undefined = "omg";
"omg" == undefined // true

كما أشارCMS ، تم تصحيح هذا في ECMAScript 5th ed. ، وغير undefined غير قابل للكتابة.

if (window.myVar) ستتضمن أيضًا هذه القيم الكاذبة ، لذا فهي ليست قوية جدًا:

false
0
""
NaN
null
undefined

بفضلMSMS للإشارة إلى أن الحالة الثالثة الخاصة بك - if (myVariable) يمكن أيضا رمي خطأ في حالتين. الأول هو عندما لم يتم تعريف المتغير الذي يرمي ReferenceError .

// abc was never declared.
if (abc) {
    // ReferenceError: abc is not defined
} 

الحالة الأخرى هي عندما يتم تعريف المتغير ، ولكن يحتوي على دالة getter التي تطرح خطأ عند استدعاء. فمثلا،

// 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?
}

الطريقة الأكثر موثوقية في التحقق من عدم undefined هي استخدام void 0 .

هذا متوافق مع المتصفحات الأحدث والأقدم ، على حد سواء ، ولا يمكن الكتابة فوقه مثل window.undefined يمكن في بعض الحالات.

if( myVar === void 0){
    //yup it's undefined
}

بعض السيناريوهات توضح نتائج الإجابات المختلفة: http://jsfiddle.net/drzaus/UVjM4/

(لاحظ أن استخدام var in الاختبارات يُحدث فرقًا عندما يكون في غلاف مغلق)

رمز للرجوع اليها:

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

والنتائج:

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

تحتاج إلى استخدام typeof .

if (typeof something != "undefined") {
    // ...
}

على العكس منThomas Eding الجواب:

إذا نسيت أن أعلن myVar في رمز بلدي ، ثم سوف أحصل على myVar is not defined .

لنأخذ مثالًا حقيقيًا:

لدي اسم متغير ، لكنني لست متأكداً مما إذا تم الإعلان عنه في مكان ما أم لا.

ثم سوف يساعد الجواب Anurag @:

var myVariableToCheck = 'myVar';
if (window[myVariableToCheck] === undefined)
    console.log("Not declared or declared, but undefined.");

// Or you can check it directly 
if (window['myVar'] === undefined) 
    console.log("Not declared or declared, but undefined.");

في Google Chrome ، كان ما يلي أسرع قليلاً من اختبار typeof :

if (abc === void 0) {
    // Undefined
}

كان الفرق مهملاً. ومع ذلك ، فإن هذا الرمز أكثر إيجازًا ، وأكثر وضوحًا في لمحة إلى شخص يعرف ما هو void 0 يعني. مع ذلك ، يجب ملاحظة أنه يجب إعلان abc .

كان كل من typeof و void أسرع بشكل ملحوظ من مقارنة مباشرة ضد undefined . استخدمت تنسيق الاختبار التالي في وحدة تحكم مطوري Chrome:

var abc;
start = +new Date();
for (var i = 0; i < 10000000; i++) {
    if (TEST) {
        void 1;
    }
}
end = +new Date();
end - start;

كانت النتائج كما يلي:

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

لاحظ أن الصف الأول بالثواني milli بينما يكون الصف الثاني في ثوان nano . فرق قدره 3.4 نانوثانية لا شيء. كانت الأوقات متسقة جدًا في الاختبارات اللاحقة.


    var x;
    if (x === undefined) {
        alert ("I am declared, but not defined.")
    };
    if (typeof y === "undefined") {
        alert ("I am not even declared.")
    };

    /* One more thing to understand: typeof ==='undefined' also checks 
       for if a variable is declared, but no value is assigned. In other 
       words, the variable is declared, but not defined. */

    // Will repeat above logic of x for typeof === 'undefined'
    if (x === undefined) {
        alert ("I am declared, but not defined.")
    };
    /* So typeof === 'undefined' works for both, but x === undefined 
       only works for a variable which is at least declared. */

    /* Say if I try using typeof === undefined (not in quotes) for 
       a variable which is not even declared, we will get run a 
       time error. */

    if (z === undefined) {
        alert ("I am neither declared nor defined.")
    };
    // I got this error for z ReferenceError: z is not defined 

if (typeof foo == 'undefined') {
 // Do something
};

لاحظ أن المقارنة الصارمة ( !== ) ليست ضرورية في هذه الحالة ، لأن typeof سيؤدي دائمًا إلى عرض سلسلة.





undefined