typeof! == không xác định rõ ràng so với!


491

Tôi thường thấy mã JavaScript kiểm tra các tham số không xác định, v.v ... theo cách này:

if (typeof input !== "undefined") {
    // do stuff
}

Điều này có vẻ lãng phí, vì nó liên quan đến cả tra cứu kiểu và so sánh chuỗi, không đề cập đến tính dài dòng của nó. Nó cần thiết bởi vì undefinedcó thể được đổi tên, mặc dù.

Câu hỏi của tôi là:
Làm thế nào mã đó tốt hơn so với phương pháp này:

if (null != input) {
    // do stuff
}

Theo tôi biết, bạn không thể xác định lại null, vì vậy nó sẽ không bị phá vỡ bất ngờ. Và, do sự ép buộc kiểu của !=toán tử, điều này kiểm tra cả hai undefinednull... thường chính xác những gì bạn muốn (ví dụ: đối với các tham số chức năng tùy chọn).

Tuy nhiên, hình thức này dường như không phổ biến và thậm chí nó còn khiến cho JSLint la mắng bạn vì đã sử dụng !=toán tử độc ác .

Tại sao điều này được coi là phong cách xấu?


13
@ Marcel, không có sự khác biệt thực sự, nhưng có hai lý do để làm điều đó. Một, là đối với một số nó là rõ ràng hơn để đọc. Và lý do thứ hai, là nó ngăn chặn việc ghi đè ngẫu nhiên một biến. Bạn đã bao giờ làm điều này: if (foo = "value") khi có ý định so sánh. Nếu bạn có thói quen đảo ngược biến, trong toán tử gán / so sánh, thì bạn sẽ không gặp vấn đề đó.
Layke

29
Đối với một số (bao gồm cả tôi) điều này thực sự khó đọc hơn. Ngoài ra, hầu hết các IDE đều cảnh báo bạn về sự phân công tình cờ. Nhưng tôi vẫn sử dụng hình thức này nếu biến so sánh là rất dài. YMMV.
johndodo

15
@MarcelKorpel Đây được gọi là "điều kiện Yoda": umumble.com/bloss/Programming/321
kol

55
Nó khó đọc hơn. Người ta không nói "Không rỗng là chai".
Noel Abrahams

11
if (null != input)chỉ là "Yoda Nói" với người nói tiếng Anh (Trong số tôi là .... uuammmmm) vì vậy nếu chúng tương đương với cùng một thứ thì đó thực sự chỉ là ngữ nghĩa. IMHO.
webLacky3rdClass

Câu trả lời:


710

typeof an toàn hơn vì nó cho phép định danh chưa bao giờ được khai báo trước đó:

if(typeof neverDeclared === "undefined") // no errors

if(neverDeclared === null) // throws ReferenceError: neverDeclared is not defined

3
if ((typeof neverDeclared! == "không xác định") && (neverDeclared! == null)) {return true; } khác {trả về false; }
Anthony DiSanti

88
Sử dụng === khi so sánh với null / không xác định.
MyGGaN

47
@MyGGaN chỉ khi bạn muốn phân biệt giữa hai. Trong nhiều trường hợp, ==có thể tốt hơn, bởi vì nó kiểm tra cả null và không xác định.
seanmonstar

10
Tôi không thể tìm thấy bất kỳ sự khác biệt nào giữa typeof somevar == 'không xác định' và typeof somevar === 'không xác định', bởi vì typeof luôn trả về chuỗi. Đối với null nó sẽ trả về 'đối tượng'. Hay có thể là tôi sai?
TomTom

2
Tôi tin rằng nhận xét của @ TomTom là mấu chốt của vấn đề - Tôi không thể hiểu tại sao người ta sẽ sử dụng toán tử !==hoặc ===toán tử khi so sánh một giá trị có loại được biết là một chuỗi.
Nicolas Rinaudo

49

Nếu biến được khai báo (với vartừ khóa, như một đối số hàm hoặc là biến toàn cục), tôi nghĩ cách tốt nhất để làm điều đó là:

if (my_variable === undefined)

jQuery làm điều đó, vì vậy nó đủ tốt cho tôi :-)

Nếu không, bạn sẽ phải sử dụng typeofđể tránh a ReferenceError.

Nếu bạn dự kiến ​​không xác định được xác định lại, bạn có thể bọc mã của mình như thế này:

(function(undefined){
    // undefined is now what it's supposed to be
})();

Hoặc có được nó thông qua các voidnhà điều hành:

const undefined = void 0;
// also safe

1
Nếu không xác định đã được xác định, thì bạn sẽ không chuyển nó đến hàm ẩn danh của mình thông qua một tham số có tên là không xác định, không thực hiện được gì?
Anthony DiSanti

20
@Anthony DiSanti: Không, undefinedlà tên được đặt cho tham số hàm, không phải giá trị của nó. Không có gì được truyền cho hàm, nghĩa là giá trị của tham số đầu tiên không được xác định.
Joey Adams

3
Ah sai lầm của tôi, cảm ơn đã theo dõi. Tôi đã bỏ phiếu bầu của tôi xuống, xin lỗi về điều đó.
Anthony DiSanti

2
Tại sao viết một ngoại lệ để xử lý không xác định được khai báo bởi nhà phát triển khác khi bạn có thể thực hiện chính xác để bắt đầu? jQuery bao bọc hàm ẩn danh ban đầu khi bạn hiển thị trong hàm của mình để đảm bảo không xác định không được xác định và để giảm kích thước rút gọn. Đơn giản chỉ cần đặt nếu nó có thể mang lại kết quả bất ngờ để làm theo cách này, tại sao lại mạo hiểm vì lập trình lười biếng để tránh gõ ra (biến typeof === 'không xác định'). Điều gì sẽ xảy ra nếu chúng ta muốn (typeof biến === 'object') nếu chúng ta cung cấp một biến mặc định cũng là một đối tượng để chúng ta có thể làm (biến === object)?
fyrye

28

cách tốt:

if(typeof neverDeclared == "undefined") //no errors

Nhưng cách tốt nhất là kiểm tra qua:

if(typeof neverDeclared === typeof undefined) //also no errors and no strings

6
var undinite = function () {}; if (typeof neverDeclared === typeof không xác định); neverDecalred! = 'chức năng'; jsfiddle.net/hbPZ5 trả về typeof var; trả về một chuỗi. Không có lỗi hoặc chuỗi nhưng sẽ không luôn luôn cho kết quả mong đợi. Các nhà phát triển được cấp không nên khai báo không xác định, nhưng có một số khung và thư viện thực hiện.
fyrye

1
Tôi chủ yếu sử dụng if (typeof neverDeclared === typeof undefined) { nhưng Lint ném một lỗi. "Dự kiến ​​một chuỗi và thay vào đó đã thấy 'typeof'." Làm thế nào bạn sẽ nhận được xung quanh lỗi này? Thay vào đó, chúng ta có nên gửi yêu cầu của Lint và sử dụng "cách tốt" không?
Ayelis

2
@fyrye Bạn có biết bất kỳ thư viện / khung công tác JavaScript nào thực sự đột biến không xác định không? Tôi biết điều đó là có thể; nhưng tôi muốn tìm một ví dụ hoang dã về "Đây là nơi bạn có thể bắt gặp Wildebeest khó chịu này!"
bigtunacan

4
typeof neverDeclared === typeof void 0;-D
Alex Yaroshevich

1
Nó dễ bị lỗi, vì thực tế bạn chỉ đang dựa vào một biến nhất định ("không xác định") không được xác định. Mà có thể sai, như các bài viết khác cho thấy. Bạn luôn có thể làm if(typeof neverDeclared === typeof undefined_variable_with_a_name_assumed_to_be_never_defined) {nhưng nó khá dài.
Pierre-Olivier Vares

12

Bạn không nên thực sự lo lắng về việc không xác định được đổi tên. Nếu ai đó đổi tên không xác định, bạn sẽ gặp nhiều rắc rối hơn chỉ một vài nếu kiểm tra không thành công. Nếu bạn thực sự muốn bảo vệ mã của mình, hãy bọc nó trong IFFE (biểu thức hàm được gọi ngay lập tức) như thế này:

(function($, Backbone, _, undefined) {
    //undefined is undefined here.
})(jQuery, Backbone, _);

Nếu bạn đang làm việc với các biến toàn cục (đã sai) trong môi trường trình duyệt, tôi sẽ kiểm tra xem không xác định như thế này:

if(window.neverDefined === undefined) {
    //Code works
}

Vì các biến toàn cục là một phần của đối tượng cửa sổ, bạn chỉ cần kiểm tra lại không xác định thay vì truyền vào chuỗi và so sánh chuỗi.

Trên hết, tại sao các biến của bạn không được xác định? Tôi đã thấy rất nhiều mã nơi họ kiểm tra sự tồn tại của biến và thực hiện một số hành động dựa trên đó. Chưa một lần tôi thấy cách tiếp cận này là chính xác.


1
Xác nhận đầu vào và kiểm tra phụ thuộc là cả hai lý do tốt để sử dụng điều này. Nếu tôi có các tệp Javascript phụ thuộc vào các tệp khác đã tải hoặc các đối tượng init đã được khai báo, thì việc kiểm tra các đối tượng hoặc thuộc tính của tệp là phụ thuộc vào việc không xác định và ném một ngoại lệ đẹp thay vì để tập lệnh của bạn thất bại ở đâu đó không thể đoán trước.
AmericanUmlaut

Có vẻ như bạn có thể cần một cái gì đó trong các dòng của AMD (allow.js)
Peeter

1
Hoặc tôi có thể chỉ muốn thực hiện một so sánh rất đơn giản thay vì đưa một thư viện khác vào dự án của mình :)
AmericanUmlaut

Quá muộn để chỉnh sửa :(. Muốn thêm - allow.js cũng không phải là giải pháp phù hợp để xác thực đầu vào (các đối tượng init mà tôi đã đề cập trong nhận xét ban đầu của tôi). các giá trị trước khi tập lệnh được tải, thật hữu ích khi ném ngoại lệ nếu chúng không được xác định.
AmericanUmlaut

1
Không, bởi vì typeof trả về một chuỗi. Vì vậy, typeof không xác định trả về "không xác định". window.input! == không xác định (nếu biến của bạn nằm trong spoce toàn cầu)
Peeter

5

Nếu bạn thực sự lo lắng về việc không xác định được xác định lại, bạn có thể bảo vệ chống lại điều này bằng một số phương thức trợ giúp như thế này:

function is_undefined(value) {
   var undefined_check; // instantiate a new variable which gets initialized to the real undefined value
   return value === undefined_check;
}

Điều này hoạt động bởi vì khi ai đó viết undefined = "foo" , anh ta chỉ cho phép tên undefined tham chiếu đến một giá trị mới, nhưng anh ta không thay đổi giá trị thực tế của undefined.


1
Tuy nhiên, giờ đây bạn đã giới thiệu một lệnh gọi hàm, điều này sẽ gây hại cho hiệu suất.
Tim Down

Tôi không nghĩ rằng lệnh gọi hàm này sẽ giết chết hiệu năng, nhiều khả năng DOM sẽ là nút cổ chai. Nhưng dù sao, nếu bạn có chức năng ẩn danh lớn thông thường chứa thư viện của bạn bất cứ điều gì, bạn cũng có thể xác định undefined_checkở trên cùng và sau đó chỉ cần sử dụng nó ở mọi nơi trong mã của bạn.
Ivo Wetzel

1
Đồng ý, và tôi không nói đây là một ý tưởng tồi. Thật đáng để chỉ ra rằng việc gọi chức năng này sẽ hoạt động chậm hơn so với việc typeofkiểm tra.
Tim Down

Tôi nghĩ rằng chức năng này đủ đơn giản để nó được nội tuyến, vì vậy hiệu suất sẽ không bị ảnh hưởng.
huyz

4
@TimDown: viết mã đầu tiên, có thể đọc được. viết mã thứ hai, có thể duy trì được, và sau đó, nếu nó thực sự chậm. sau đó suy nghĩ về hiệu suất.
andreas 15/11/13

4

Bạn cũng có thể sử dụng toán tử void để lấy giá trị không xác định:

if (input !== void 0) {
    // do stuff    
}

(Và vâng, như đã lưu ý trong một câu trả lời khác, điều này sẽ gây ra lỗi nếu biến không được khai báo, nhưng trường hợp này thường có thể được loại trừ bằng cách kiểm tra mã hoặc bằng cách tái cấu trúc mã, ví dụ như sử dụng window.input !== void 0để kiểm tra các biến toàn cục hoặc thêm var input.)


1

Tôi thực sự đã đi qua nếu (typeof input !== 'undefined')trong kịch bản này, nơi nó được sử dụng để cung cấp các tham số chức năng mặc định:

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';

  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

ES6 cung cấp các cách mới để giới thiệu các tham số chức năng mặc định theo cách này:

function greet(name = 'Student', greeting = 'Welcome') {
  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

Điều này ít dài dòng và sạch sẽ hơn so với tùy chọn đầu tiên.


1

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';

  console.log(greeting,name);
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

//ES6 provides new ways of introducing default function parameters this way:

function greet2(name = 'Student', greeting = 'Welcome') {
//  return '${greeting} ${name}!';
console.log(greeting,name);
}

greet2(); // Welcome Student!
greet2('James'); // Welcome James!
greet2('Richard', 'Howdy'); // Howdy Richard!


0

(function(){

  var a= b = 3;
  var ed = 103;
  
})();



//console.log(ed); //ed is not defined

console.log("a defined? " + (typeof a !== 'undefined')); //no define
console.log("b defined? " + (typeof b !== 'undefined')); //yes define
console.log(typeof(b)); //number
console.log(typeof(4+7));   //number
console.log(b); //3
console.log(typeof("4"+"7")); //string
var e= "ggg";
console.log(typeof(e)); //string
 var ty=typeof(b);
console.log(ty); //number
console.log(typeof false); //boolean
console.log(typeof 1); //number
console.log(typeof 0); //number
console.log(typeof true); //boolean


console.log(typeof Math.tan);  //function
console.log(typeof function(){}); //function 

if(typeof neverDeclared == "undefined") //no errors
if(typeof neverDeclared === "undefined") //no errors

//if(neverDeclared == null) //showing error 


console.log(typeof {a:1}); //object
console.log(typeof null); //object
console.log(typeof JSON); //object
console.log(typeof Math); //object
console.log(typeof /a-z/); //object
console.log(typeof new Date()); //object

console.log(typeof afbc); //undefined
//console.log(typeof new);//error

document.write("<br> * oprator as math ");
var r=14*"4";
document.write(r);

document.write("<br> + oprator as string ");
var r=14+"44";
document.write(r);

document.write("<br> Minus Operator work as mathematic ");
var r=64-"44";
document.write(r);


document.write("<br>");
console.log(typeof(4*"7")); //returns number
console.log(typeof(4+"7")); //returns string




 
Interview Question in JavaScript


Bạn có thể cung cấp một lời giải thích?
jhpratt ĐÁNG TIN CẬY GOFUNDME

Có sáu giá trị có thể mà typeof trả về: object, boolean, function, number, string và không xác định. Toán tử typeof được sử dụng để lấy kiểu dữ liệu (trả về một chuỗi) toán hạng của nó. Toán hạng có thể là một cấu trúc bằng chữ hoặc dữ liệu, chẳng hạn như một biến, một hàm hoặc một đối tượng. Toán tử trả về kiểu dữ liệu. Cú pháp kiểu toán hạng hoặc kiểu chữ (toán hạng)
Avinash Maurya

0

var bar = null;
console.log(typeof bar === "object"); //true yes 
//because null a datatype of object

var barf = "dff";
console.log(typeof barf.constructor);//function


console.log(Array.isArray(bar));//falsss


console.log((bar !== null) && (bar.constructor === Object)); //false

console.log((bar !== null) && (typeof bar === "object"));  // logs false
//because bar!==null, bar is a object


console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function"))); //false

console.log(typeof bar === typeof object); //false
console.log(typeof bar2 === typeof undefined); //true
console.log(typeof bar3 === typeof undefinedff); //true
console.log(typeof bar2 == typeof undefined); //true

console.log((bar !== null) && (typeof bar === "object") && (toString.call(bar) !== "[object Array]")); //false


-7
if (input == undefined) { ... }

hoạt động tốt Tất nhiên đó không phải là một nullso sánh, nhưng tôi thường thấy rằng nếu tôi cần phân biệt giữa undefinednull , tôi thực sự cần phải phân biệt giữa undefinedvà chỉ bất kỳ giá trị sai, vì vậy

else if (input) { ... }

Phải không.

Nếu một chương trình xác định lại undefined nó thực sự là bản lĩnh.

Lý do duy nhất tôi có thể nghĩ đến là vì khả năng tương thích IE4, nó không hiểu undefinedtừ khóa (thật ra không phải là từ khóa), nhưng tất nhiên giá trị có thể undefined , vì vậy bạn phải có điều này:

var undefined;

và so sánh ở trên sẽ hoạt động tốt.

Trong ví dụ thứ hai của bạn, có lẽ bạn cần dấu ngoặc đơn để làm cho lint hạnh phúc?


Bạn input == undefinedsẽ trở lại truetrên một nullđầu vào.
mgol
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.