Câu hỏi Làm cách nào để kiểm tra “không xác định” trong JavaScript? [bản sao]


Câu hỏi này đã có câu trả lời ở đây:

Cách thích hợp nhất để kiểm tra xem một biến là không xác định trong JavaScript? Tôi đã nhìn thấy một số cách có thể:

if (window.myVariable)

Hoặc là

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

Hoặc là

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

1875
2017-08-02 17:53


gốc


Bạn có muốn kiểm tra chỉ có  undefined, hoặc là nullcũng? - Nick Craver♦
kiểm tra điều này stackoverflow.com/questions/27509/… - Amr Badawy
@ Robert - câu hỏi đó có câu trả lời được chấp nhận rằng câu trả lời ở đây đã chứng minh là sai - Daniel Schaffer
Xem: Làm thế nào để kiểm tra không xác định trong javascript?và cho dù một biến là không xác định và Cách xử lý ‘không xác định’ trong javascript - Shog9♦
Điều đó "trùng lặp" là về các thuộc tính đối tượng, vì vậy một số câu trả lời không áp dụng rất tốt cho câu hỏi này, hỏi về các biến. - DCShannon


Các câu trả lời:


Nếu bạn quan tâm đến việc tìm hiểu xem một biến đã được khai báo không phụ thuộc vào giá trị của nó, thì hãy sử dụng in nhà điều hành là cách an toàn nhất để đi. Hãy xem xét ví dụ này.

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

Nhưng điều này có thể không phải là kết quả dự định cho một số trường hợp, vì biến hoặc thuộc tính đã được khai báo nhưng không được khởi tạo. Sử dụng in nhà điều hành cho một kiểm tra mạnh mẽ hơn.

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

Nếu bạn muốn biết liệu biến chưa được khai báo hay có giá trị undefined, sau đó sử dụng typeof nhà điều hành.

if (typeof myVar != 'undefined')

Các typeof toán tử được đảm bảo trả về một chuỗi. So sánh trực tiếp với undefined phiền hà như undefined có thể được ghi đè.

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

Như @CMS đã chỉ ra, điều này đã được vá trong phiên bản ECMAScript thứ 5 và undefined không thể ghi.

if (window.myVar) cũng sẽ bao gồm các giá trị giả này, vì vậy nó không phải là rất mạnh mẽ:

sai
0
""
NaN
vô giá trị
chưa xác định

Nhờ @CMS để chỉ ra rằng trường hợp thứ ba của bạn - if (myVariable) cũng có thể ném một lỗi trong hai trường hợp. Đầu tiên là khi biến chưa được xác định mà ném ReferenceError.

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

Trường hợp khác là khi biến đã được xác định, nhưng có một hàm getter mà ném một lỗi khi được gọi. Ví dụ,

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

2158
2017-08-02 17:58



@Anurag, trường hợp thứ ba sẽ ném một ReferenceError nếu myVariable không phải là khai báo... - CMS
@Anurag, bạn được chào đón, vì bạn nói về ES5, có thể đáng nói đến undefined hiện được mô tả là không thể ghi, không thể định cấu hình và không thể đếm được. Vì thế, window.undefined = "omg"; chỉ đơn giản là sẽ không âm thầm hoặc ném theo chế độ nghiêm ngặt. - CMS
"Typeof" có thể được định nghĩa lại không? - CHI Coder 007
typeof là một tuyên bố ngôn ngữ, nó không thể được định nghĩa lại bất kỳ hơn nếu / else / while / for / function etc có thể được. - MooGoo
undefined là bất biến trong trình duyệt hiện đại. Cài đặt window.undefined Không lam gi cả. - Paul S.


Cá nhân tôi sử dụng

myVar === undefined

Cảnh báo: xin lưu ý rằng === được sử dụng trên == và đó myVar đã từng là khai báo (không phải xác định).


Tôi không thích typeof myVar === "undefined". Tôi nghĩ nó dài và không cần thiết. (Tôi có thể thực hiện tương tự với ít mã hơn.)

Bây giờ một số người sẽ keel over trong đau khi họ đọc này, la hét: "Chờ đợi! WAAITTT !!! undefined có thể được định nghĩa lại! "

Mát mẻ. Tôi biết cái này. Sau đó, một lần nữa, hầu hết các biến trong Javascript có thể được định nghĩa lại. Nếu bạn không bao giờ sử dụng bất kỳ số nhận dạng tích hợp nào có thể được định nghĩa lại?

Nếu bạn làm theo quy tắc này, tốt cho bạn: bạn không phải là một kẻ đạo đức giả.

Vấn đề là, để thực hiện rất nhiều công việc thực tế trong JS, các nhà phát triển cần phải dựa vào các định danh có thể xác định lại được những gì họ đang có. Tôi không nghe mọi người nói với tôi rằng tôi không nên sử dụng setTimeout bởi vì ai đó có thể

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

Điểm mấu chốt, đối số "nó có thể được định nghĩa lại" để không sử dụng nguyên === undefined là không có thật.

(Nếu bạn vẫn sợ undefined được định nghĩa lại, tại sao bạn lại tích hợp một cách mù quáng mã thư viện chưa được kiểm tra vào cơ sở mã của bạn? Hoặc thậm chí đơn giản hơn: một công cụ linting.)


Ngoài ra, giống như typeof cách tiếp cận, kỹ thuật này có thể "phát hiện" biến không khai báo:

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

Nhưng cả hai kỹ thuật này đều bị rò rỉ trong sự trừu tượng của chúng. Tôi khuyên bạn không nên sử dụng điều này hoặc thậm chí

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

Xem xét:

var iAmUndefined;

Để nắm bắt hay không biến đó được khai báo hay không, bạn có thể cần phải sử dụng đến in nhà điều hành. (Trong nhiều trường hợp, bạn có thể chỉ cần đọc mã O_o).

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

Nhưng chờ đã! Còn nữa! Điều gì xảy ra nếu một số ma thuật chuỗi nguyên mẫu đang xảy ra ...? Bây giờ ngay cả cấp trên in nhà điều hành không đủ. (Được rồi, tôi đã làm ở đây về phần này ngoại trừ nói rằng 99% thời gian, === undefined (và **** ho **** typeof) hoạt động tốt. Nếu bạn thực sự quan tâm, bạn có thể đọc về chủ đề này một mình.)


888
2017-08-02 18:26



Nó có nhiều khả năng là undefined có thể được định nghĩa lại, chỉ vì mọi người sử dụng nó để kiểm tra như vậy. Một số người thường xuyên đặt các hằng số ở phía bên trái khi thực hiện kiểm tra như vậy: if (undefined == someVariable). Nó chỉ mất một lỗi đánh máy để âm thầm xác định lại undefined: if (undefined = someVariable). - Tim Down
Tôi chưa bao giờ viết mã có undefined trên LHS. Ngay cả khi tôi đã làm, thực tế là tôi sử dụng === thay vì == làm cho lỗi đánh máy rất khó xảy ra. Nhưng thực tế là == không đúng là lo lắng nhiều. Trong mọi trường hợp, một lỗi như vậy thường dễ tìm. Loại lỗi này: typeof x == "undefned". - Thomas Eding
Làm thế nào điều này có thể được upvoted 41 lần, nó chỉ đơn giản là không hoạt động. Nếu myVar thực sự là không xác định mã sẽ ném một lỗi, và thật dễ dàng để kiểm tra - jsfiddle.net/WcM5g Cách thích hợp là typeof myVar === 'undefined'. - this.lau_
@ Laurent: Một trò đùa phải không? Điều này giả định biến được khai báo theo cách này hay cách khác, chẳng hạn như var từ khóa hoặc tham số hàm. Tôi sẽ bán linh hồn của mình trước khi tôi (cố tình) viết mã đã cố gắng hành động trên các biến không khai báo theo bất kỳ cách nào. Hãy nhớ rằng, undeclared và undefined là hai khái niệm khác nhau trong JS. - Thomas Eding
@Andy Trong C (và C ++), nó là cả hai thực hành phổ biến và tốt để đảo ngược toán hạng như thế, để tránh lỗi chính tả. if (NULL = myVar) không biên dịch và ngay lập tức bị bắt, trong khi if (myVar = NULL) tạo ra một lỗi có thể khó theo dõi tùy thuộc vào mã khác xung quanh nó. Trình biên dịch hiện đại sẽ cho bạn một cảnh báo, nhưng nhiều lập trình viên có kinh nghiệm C đã phát triển thói quen đổi thứ tự. - GrandOpener


Sử dụng typeof là sở thích của tôi. Nó sẽ hoạt động khi biến chưa bao giờ được khai báo, không giống như bất kỳ so sánh nào với == hoặc là === nhà khai thác hoặc loại cưỡng chế sử dụng if. (undefined, không giống null, cũng có thể được định nghĩa lại trong môi trường ECMAScript 3, làm cho nó không đáng tin cậy để so sánh, mặc dù gần như tất cả các môi trường phổ biến hiện nay đều tương thích với ECMAScript 5 trở lên).

if (typeof someUndeclaredVariable == "undefined") {
    // Works
}

if (someUndeclaredVariable === undefined) { 
    // Throws an error
}

149
2017-08-02 18:05



Bạn có thể muốn kiểm tra xem một biến toàn cầu cụ thể có đại diện cho một phần chức năng đã được xác định hay chưa. Ví dụ: mã thư viện có thể muốn kiểm tra xem thư viện chưa được bao gồm trước đó chưa. - Tim Down
'xyz' trong cửa sổ hoặc 'xyz' trong tự tốt hơn nhiều - Jamie Pate
@JamiePate: Chỉ cần rõ ràng, tôi không đồng ý rằng 'xyz' in window là một câu trả lời tốt hơn typeof xyz == "undefined" bởi vì nó đang thử nghiệm điều sai trái. Các intoán tử kiểm tra sự tồn tại của một thuộc tính, bất kể giá trị của nó, trong khi câu hỏi ít nhất dường như hỏi làm thế nào để kiểm tra nếu giá trị của biến là undefined. Có lẽ một ví dụ tốt hơn cho tôi để chọn sẽ là var foo; "foo" in window; điều này trả về đúng trong khi foo chắc chắn là không xác định. - Tim Down
@JamiePate: Tại sao xyz === undefined tốt hơn typeof xyz == "undefined"? Đồng ý về globals, nhưng của hai chúng tôi chỉ có bạn đã được đề xuất kiểm tra tài sản của window. - Tim Down
Đó là dư thừa trong hầu hết các trường hợp (và ít có thể đọc được). Nếu bạn biết xyz là một biến được khai báo, tại sao phải trải qua sự cố thêm? Loại kiểm tra và so sánh chuỗi là chậm hơn nhiều trong một số trình duyệt, vì vậy nếu bạn làm điều đó rất nhiều trong một vòng lặp chặt chẽ, bạn sẽ mất một số hiệu suất. jsperf.com/type-of-undefined-vs-undefined/6 - Jamie Pate


Bạn cần sử dụng typeof .

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

51
2018-06-06 20:22



Hay là something !== undefined, giả sử bạn đã làm xong var undefined, thận trọng. - James
Rất vui được thấy bạn đã thêm dấu ngoặc kép ngay bây giờ. Tuy nhiên, như đã đề cập trong câu trả lời của tôi, lưu ý rằng so sánh nghiêm ngặt (!==) không cần thiết trong trường hợp này, vì typeof sẽ luôn trả về một chuỗi. - Mathias Bynens
Mathias: sử dụng so sánh nghiêm ngặt hoặc không nghiêm ngặt ở đây là vấn đề sở thích cá nhân. Cả hai sẽ luôn hoạt động và không chính xác hơn. Nó có thể phụ thuộc vào việc vị trí mặc định của bạn có luôn luôn sử dụng so sánh nghiêm ngặt hay không, trừ khi yêu cầu loại cưỡng chế (như Crockford khuyến nghị) hoặc bạn muốn sử dụng so sánh không nghiêm ngặt trừ khi yêu cầu độ nghiêm ngặt. - Tim Down


Nếu nó không xác định, nó sẽ không bằng một chuỗi có chứa các ký tự "không xác định", vì chuỗi không được xác định.

Bạn có thể kiểm tra loại biến:

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

Đôi khi bạn thậm chí không phải kiểm tra loại. Nếu giá trị của biến không thể đánh giá sai khi được đặt (ví dụ nếu đó là hàm), thì bạn chỉ có thể đánh giá biến. Thí dụ:

if (something) {
  something(param);
}

20
2018-06-06 20:23



Không cần các dấu ngoặc đơn: typeof là một toán tử, không phải là một hàm. - Tim Down
@Tim - Nó có thể được sử dụng cả hai cách. - Nick Craver♦
@Tim: @Nick là chính xác. Xem developer.mozilla.org/en/Core_Javascript_1.5_Reference/… - Mathias Bynens
Vâng, tôi biết rằng nó công trinh với các dấu ngoặc đơn, đó là vì các dấu ngoặc đơn ở đây tạo thành toán tử nhóm mà chỉ đơn giản là đánh giá và trả về toán hạng bên trong. Tôi chỉ nói rằng họ không cần thiết. - Tim Down


Một số kịch bản minh họa kết quả của các câu trả lời khác nhau: http://jsfiddle.net/drzaus/UVjM4/

(Lưu ý rằng việc sử dụng var cho in kiểm tra tạo sự khác biệt khi trong một wrapper phạm vi)

Mã để tham khảo:

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

Và kết quả:

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

17
2018-01-13 15:39



lưu ý việc sử dụng undefined trong phạm vi bao bọc; điều này không chỉ bảo vệ chống lại trường hợp (bất thường) của "oh nhưng undefined có thể được định nghĩa lại "" nhưng cũng 'giúp' bằng cách rút gọn. - drzaus


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

Lưu ý rằng so sánh nghiêm ngặt (!==) không cần thiết trong trường hợp này, vì typeof sẽ luôn trả về một chuỗi.


16
2018-06-06 20:26



Có gì với dấu chấm phẩy (};)? - James
@ J-P: Dấu chấm phẩy sau cú đúp đóng chỉ là một tuyên bố trống. - Gumbo
@ Gumbo, xin lỗi, những gì tôi có nghĩa là để hỏi là: "Mục đích của việc bán đại tràng là gì?" - James
Tôi đã không gặp một thợ mỏ không thể xử lý if(){} không có ; ... Bạn đang đề cập đến minifiers nào? Bạn nói rằng đây là cách bạn kết thúc mọi tuyên bố khác ... Tôi đoán đó là sự thật. Nhưng, một câu lệnh chặn {} đã là một tuyên bố trong và của riêng nó. Thêm một ; làm cho nó hai câu, về mặt kỹ thuật. Cú pháp, nó dư thừa. Ngay cả việc chèn dấu chấm phẩy tự động cũng sẽ không thêm dấu chấm phẩy ở đó ... - James
@ J-P: Tôi đoán tôi đã bắt đầu thực hiện nó năm trước sau khi đọc tài liệu Packer. Packer hy vọng dấu chấm phẩy sau function() {} khai báo. Bạn nói đúng - dường như không cần thiết sau if câu nói, nhưng bằng cách nào đó tôi vẫn nghĩ nó có ý nghĩa. - Mathias Bynens


Trong bài viết này Tôi đọc những khung như Underscore.js sử dụng chức năng này:

function isUndefined(obj){
    return obj === void 0;
}

15
2017-12-19 10:42





Cách đáng tin cậy nhất mà tôi biết về việc kiểm tra undefined là để sử dụng void 0.

Điều này tương thích với các trình duyệt mới hơn và cũ hơn, giống nhau và không thể bị ghi đè như window.undefined có thể trong một số trường hợp.

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

9
2018-02-19 13:20



Điều này được đánh giá thấp và IMHO một cách thích hợp hơn để kiểm tra cái gì đó không được xác định. - Brian M. Hunt
Hoàn toàn chính xác, nhưng tôi tưởng tượng nếu undefined !== void 0, bạn có thể có các vấn đề nghiêm trọng khác trong codebase đã nói. - Thomas Eding


Cá nhân, tôi luôn sử dụng như sau:

var x;
if( x === undefined) {
    //Do something here
}
else {
   //Do something else here
}

Thuộc tính window.undefined không thể ghi trong tất cả các trình duyệt hiện đại (JavaScript 1.8.5 hoặc mới hơn). Từ tài liệu của Mozilla: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined, Tôi thấy điều này: Một lý do để sử dụng typeof () là nó không ném một lỗi nếu biến chưa được xác định.

Tôi thích có cách tiếp cận sử dụng

x === undefined 

bởi vì nó thất bại và thổi lên trong khuôn mặt của tôi hơn là âm thầm đi qua / thất bại nếu x chưa được khai báo trước đây. Điều này cảnh báo cho tôi rằng x không được khai báo. Tôi tin rằng tất cả các biến được sử dụng trong JavaScript nên được khai báo.


9
2017-12-20 10:24



bạn có thể redeclare undefined sử dụng trình bao bọc phạm vi: (function($, undefined){ /* undefined is 'abc' in here */ })(jQuery, 'abc');, đó là lý do tại sao ppl phàn nàn rằng nó về mặt kỹ thuật không an toàn trừ khi bạn chắc chắn 100% bạn biết mã của bạn đang được chạy ở đâu. - drzaus
Điểm tuyệt vời về muốn biến không khai báo để thổi lên - điều này không xảy ra với typeof. - FruitBreak