Bagaimana cara memeriksa apakah suatu objek adalah kencan?

601

Saya memiliki bug yang mengganggu di halaman web:

date.GetMonth () bukan fungsi

Jadi, saya kira saya melakukan sesuatu yang salah. Variabel datebukan objek bertipe Date. Bagaimana saya bisa memeriksa datatype dalam Javascript? Saya mencoba menambahkan if (date), tetapi tidak berhasil.

function getFormatedDate(date) {
    if (date) {
       var month = date.GetMonth();
    }
}

Jadi, jika saya ingin menulis kode defensif dan mencegah tanggal (yang bukan salah) diformat, bagaimana saya melakukannya?

Terima kasih!

UPDATE: Saya tidak ingin memeriksa format tanggal, tetapi saya ingin memastikan bahwa parameter yang dikirimkan ke metode getFormatedDate()bertipe Date.

Martin
sumber
Dalam hal ini juga harus divalidasi apakah tanggalnya bukan Invalid Date: stackoverflow.com/a/44198641/5846045
Boghyon Hoffmann

Jawaban:

1110

Sebagai alternatif untuk mengetik melalui bebek

typeof date.getMonth === 'function'

Anda dapat menggunakan instanceofoperator, yaitu Tapi itu akan mengembalikan true untuk tanggal yang tidak valid juga, misalnya new Date('random_string')juga merupakan contoh Date

date instanceof Date

Ini akan gagal jika objek melewati batas bingkai.

Solusi untuk ini adalah memeriksa kelas objek melalui

Object.prototype.toString.call(date) === '[object Date]'
Christoph
sumber
29
Karena minat, apakah Anda tahu alasan kegagalan ini ketika melewati batas bingkai?
Simon Lieschke
85
@Simon: JS global adalah lokal ke objek global saat ini (alias windowatau self); frame yang berbeda memiliki objek global mereka sendiri, dan properti mereka (yaitu global) merujuk ke objek yang berbeda: Datedalam frame1 adalah objek fungsi yang berbeda dari Datepada frame2; hal yang sama berlaku untuk Date.prototype, yang merupakan alasan instanceofkegagalan: Date.prototypedari frame1 bukan bagian dari rantai prototipe Datecontoh dari frame2
Christoph
9
Christoph, apa yang kau sebut "bingkai"? IFRAME, setiap frame dalam FRAMESET atau sesuatu yang lain (maksud saya JS-spesifik, bukan HTML-hal)?
Paul
12
new Date('something') instanceof Datekembali truedi Chrome. Itu tidak akan berhasil kalau begitu.
krillgar
12
Mendeteksi objek tipe Date (sebagai lawan dari Object atau string) dan memvalidasi objek yang Anda harapkan sebagai Date adalah dua tugas berbeda. Ada beberapa situasi di mana input ke fungsi Anda bisa menjadi salah satu dari sejumlah tipe data yang berbeda. Dalam kasus saya, saya dapat mempercayai bahwa objek Date apa pun yang saya dapatkan adalah valid (itu tidak datang langsung dari klien) Jika validasi adalah masalah, berikut adalah posting dengan sejumlah opsi. stackoverflow.com/questions/1353684/…
Michael Blackburn
125

Anda dapat menggunakan kode berikut:

(myvar instanceof Date) // returns true or false
SF_dev
sumber
6
Mengapa ini bukan jawaban yang diterima atau lebih dipilih? Cukup memeriksa apakah tanggal memiliki properti .getMonth dapat memicu false positive.
doremi
24
Contohnya dapat memicu negatif palsu, lihat komentar Christoph untuk jawabannya sendiri.
Marco Mariani
2
@doremi Ini adalah demo instanceofpemicu false negative: jsbin.com/vufufoq/edit?html,js,console
Boghyon Hoffmann
69

Untuk memeriksa apakah nilainya adalah tipe yang valid dari objek JS-date standar, Anda dapat menggunakan predikat ini:

function isValidDate(date) {
  return date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date);
}
  1. datememeriksa apakah parameter itu bukan nilai falsy ( undefined, null, 0, "", dll ..)
  2. Object.prototype.toString.call(date)mengembalikan representasi string asli dari jenis objek yang diberikan - Dalam kasus kami "[object Date]". Karena date.toString()mengesampingkan metode induknya , kita perlu .callatau .applymetode dari Object.prototypelangsung yang ..
  3. !isNaN(date)akhirnya memeriksa apakah nilainya bukan Invalid Date.
Boghyon Hoffmann
sumber
1
Wow isNaNbisa digunakan untuk mengecek a Date. Itu beberapa level PHP yang tidak waras.
Nick
@Nick kencan adalah nomor sekalipun.
Josiah
@Josiah Nah, yakin, menghapus semua konteks ada timestamp ada: typeof Date.now() === "number", tapi: typeof new Date() === "object". Lebih realistis lagi, kencan adalah waktu dan lokasi di luar angkasa.
Nick
39

Fungsinya getMonth()bukan GetMonth().

Lagi pula, Anda dapat memeriksa apakah objek memiliki properti getMonth dengan melakukan ini. Itu tidak selalu berarti objek adalah Tanggal, sembarang objek yang memiliki properti getMonth.

if (date.getMonth) {
    var month = date.getMonth();
}
Chetan Sastry
sumber
3
Periksa apakah itu bisa dihubungi:if (date.getMonth && typeof date.getMonth === "function") {...}
Aloso
20

Seperti yang ditunjukkan di atas, mungkin paling mudah untuk hanya memeriksa apakah fungsi tersebut ada sebelum menggunakannya. Jika Anda benar-benar peduli bahwa itu adalah Date, dan bukan hanya objek dengan getMonth()fungsi, coba ini:

function isValidDate(value) {
    var dateWrapper = new Date(value);
    return !isNaN(dateWrapper.getDate());
}

Ini akan membuat klon nilai jika itu adalah Date, atau membuat tanggal yang tidak valid. Anda kemudian dapat memeriksa apakah nilai tanggal yang baru tidak valid atau tidak.

bdukes
sumber
1
Ini berhasil untuk saya, terima kasih. Namun, jika Anda melewati satu digit seperti 0, atau 1, itu memperlakukan itu sebagai Tanggal yang valid ... ada pemikiran?
Ricardo Sanchez
Benar, @RicardoSanchez. Anda mungkin ingin menggunakan jawaban yang diterima ( Object.prototype.toString.call(value) === '[object Date]') jika memungkinkan Anda akan mendapatkan nomor. Metode dalam jawaban ini benar-benar memberi tahu Anda apakah valuedapat dikonversi ke Date.
bdukes
18

Untuk semua tipe saya membuat fungsi prototipe Object. Ini mungkin berguna bagi Anda

Object.prototype.typof = function(chkType){
      var inp        = String(this.constructor),
          customObj  = (inp.split(/\({1}/))[0].replace(/^\n/,'').substr(9),
          regularObj = Object.prototype.toString.apply(this),
          thisType   = regularObj.toLowerCase()
                        .match(new RegExp(customObj.toLowerCase()))
                       ? regularObj : '[object '+customObj+']';
     return chkType
            ? thisType.toLowerCase().match(chkType.toLowerCase()) 
               ? true : false
            : thisType;
}

Sekarang Anda dapat memeriksa semua jenis seperti ini:

var myDate     = new Date().toString(),
    myRealDate = new Date();
if (myRealDate.typof('Date')) { /* do things */ }
alert( myDate.typof() ); //=> String

[ Edit maret 2013 ] berdasarkan kemajuan wawasan, ini adalah metode yang lebih baik:

Object.prototype.is = function() {
        var test = arguments.length ? [].slice.call(arguments) : null
           ,self = this.constructor;
        return test ? !!(test.filter(function(a){return a === self}).length)
               : (this.constructor.name ||
                  (String(self).match ( /^function\s*([^\s(]+)/im)
                    || [0,'ANONYMOUS_CONSTRUCTOR']) [1] );
}
// usage
var Some = function(){ /* ... */}
   ,Other = function(){ /* ... */}
   ,some = new Some;
2..is(String,Function,RegExp);        //=> false
2..is(String,Function,Number,RegExp); //=> true
'hello'.is(String);                   //=> true
'hello'.is();                         //-> String
/[a-z]/i.is();                        //-> RegExp
some.is();                            //=> 'ANONYMOUS_CONSTRUCTOR'
some.is(Other);                       //=> false
some.is(Some);                        //=> true
// note: you can't use this for NaN (NaN === Number)
(+'ab2').is(Number);                 //=> true
KooiInc
sumber
10

UnderscoreJS dan Lodash memiliki fungsi yang disebut .isDate()yang tampaknya persis apa yang Anda butuhkan. Layak untuk melihat implementasi masing-masing: Lodash isDate , UnderscoreJs

longsoran1
sumber
8

Cara terbaik yang saya temukan adalah:

!isNaN(Date.parse("some date test"))
//
!isNaN(Date.parse("22/05/2001"))  // true
!isNaN(Date.parse("blabla"))  // false
jspassov
sumber
Ini tidak berhasil. Baris Anda yang sebenarnya sebenarnya salah dan pertanyaannya adalah tentang memeriksa apakah suatu objek adalah objek tanggal ...
Clint
1
Jawaban @jspassov lebih akurat dengan apakah string adalah tanggal atau tidak. Itu yang saya cari. Terima kasih!!
Anant
Ini adalah jawaban terbaik untuk hanya memeriksa apakah sebuah string adalah tanggal atau tidak
James Gentes
3

Anda bisa memeriksa apakah ada fungsi khusus untuk objek Date:

function getFormatedDate(date) {
    if (date.getMonth) {
        var month = date.getMonth();
    }
}
Powerlord
sumber
3

Alih-alih semua solusi Anda dapat menggunakan yang berikut:

dateVariable = new Date(date);
if (dateVariable == 'Invalid Date') console.log('Invalid Date!');

Saya menemukan retasan ini lebih baik!

ini Harshad
sumber
2

Anda juga dapat menggunakan formulir pendek

function getClass(obj) {
  return {}.toString.call(obj).slice(8, -1);
}
alert( getClass(new Date) ); //Date

atau sesuatu seperti ini:

(toString.call(date)) == 'Date'
pavlo
sumber
2

Saya telah menggunakan cara yang jauh lebih sederhana tetapi saya tidak yakin apakah ini hanya tersedia di ES6 atau tidak.

let a = {name: "a", age: 1, date: new Date("1/2/2017"), arr: [], obj: {} };
console.log(a.name.constructor.name); // "String"
console.log(a.age.constructor.name);  // "Number"
console.log(a.date.constructor.name); // "Date"
console.log(a.arr.constructor.name);  // "Array"
console.log(a.obj.constructor.name);  // "Object"

Namun, ini tidak akan berfungsi pada nol atau tidak ditentukan karena mereka tidak memiliki konstruktor.

mjwrazor
sumber
Setiap objek yang dibuat khusus dengan nama konstruktor "Tanggal" "Date"juga kembali yang sama berisikonya dengan hanya memeriksa apakah parameter tersebut memiliki getMonthproperti.
Boghyon Hoffmann
2
@ boghyon terdengar seperti siapa yang membuat objek dengan nama konstruktor dari perpustakaan standar Javascript yang sudah ditentukan sebelumnya tidak mengikuti praktik terbaik di tempat pertama. Itu akan seperti mengunduh lodash kemudian membuat modul lodash Anda sendiri dan mengharapkan sesuatu berfungsi.
mjwrazor
1

Fungsi ini akan kembali truejika itu Tanggal atau falsesebaliknya:

function isDate(myDate) {
    return myDate.constructor.toString().indexOf("Date") > -1;
} 
Jahid
sumber
1
isDate(new (function AnythingButNotDate(){ })())kembalitrue
Boghyon Hoffmann
1

Varian lain:

Date.prototype.isPrototypeOf(myDateObject)
Vadim
sumber
Bagus dan pendek! Namun sayangnya, ia memiliki masalah yang sama denganinstanceof .
Boghyon Hoffmann
@BoghyonHoffmann jika iFrame mungkin terlihat seperti: iWindow.Date.prototype.isPrototypeOf(iWindow.date); // true iWindow.date instanceof iWindow.Date; // true
Vadim
1

Pendekatan menggunakan try / catch

function getFormatedDate(date = new Date()) {
  try {
    date.toISOString();
  } catch (e) {
    date = new Date();
  }
  return date;
}

console.log(getFormatedDate());
console.log(getFormatedDate('AAAA'));
console.log(getFormatedDate(new Date('AAAA')));
console.log(getFormatedDate(new Date(2018, 2, 10)));

codeKonami
sumber
0

Sebenarnya tanggal akan bertipe Object. Tetapi Anda dapat memeriksa apakah objek memiliki getMonthmetode dan apakah itu bisa dipanggil.

function getFormatedDate(date) {
    if (date && date.getMonth && date.getMonth.call) {
       var month = date.getMonth();
    }
}
vartec
sumber
2
Jawaban Christoph lebih akurat. Memiliki properti 'panggilan' tidak selalu berarti itu adalah fungsi!
Chetan Sastry
-1

Kami juga dapat memvalidasinya dengan kode di bawah ini

var a = new Date();
a.constructor === Date
/*
true
*/

masukkan deskripsi gambar di sini

Arun
sumber
Konstruktor function Date() {/*...*/}juga Date. Yaitu hanya membandingkan fungsi konstruktor terlalu rawan kesalahan yang sering menghasilkan positif palsu. Lewati tipe objek yang ditentukan pengguna dengan stackoverflow.com/a/44198641/5846045
Boghyon Hoffmann
-1

Terinspirasi oleh jawaban ini , solusi ini berfungsi dalam kasus saya (saya perlu memeriksa apakah nilai yang diterima dari API adalah tanggal atau tidak):

!isNaN(Date.parse(new Date(YourVariable)))

Dengan cara ini, jika itu adalah string acak yang berasal dari klien, atau objek lain, Anda dapat mengetahui apakah itu adalah objek seperti Date.

Mohammad Ganji
sumber
-2

Tidak bisakah Anda menggunakan saja

function getFormatedDate(date) {
    if (date.isValid()) {
       var month = date.GetMonth();
    }
}
Pemarah
sumber
1
Tidak, hanya objek tanggal yang memiliki isValidmetode
nikk wong
2
@grumpy @nikkwong Tidak dan tidak. Objek tanggal standar tidak punya isValid. Hanya moment.js yang memiliki API seperti itu.
Boghyon Hoffmann