Як перевірити, чи є об’єктом дата?


601

У мене на веб-сторінці дратівлива помилка:

date.GetMonth () не є функцією

Отже, я гадаю, що роблю щось не так. Змінна dateне є об'єктом типу Date. Як я можу перевірити тип даних у Javascript? Я спробував додати if (date), але це не працює.

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

Отже, якщо я хочу написати захисний код і не допустити форматування дати (яка не одна), як це зробити?

Дякую!

ОНОВЛЕННЯ: Я не хочу перевіряти формат дати, але хочу бути впевненим, що параметр, переданий методу, getFormatedDate()має тип Date.


У разі , якщо воно має бути також підтверджено чи дата не є Invalid Date: stackoverflow.com/a/44198641/5846045
Boghyon Hoffmann

Відповіді:


1109

Як альтернатива набору качки через

typeof date.getMonth === 'function'

Ви можете скористатися instanceofоператором, тобто він поверне істинне значення і для недійсних дат, наприклад, new Date('random_string')це також екземпляр Date

date instanceof Date

Це не вдасться, якщо об'єкти передаються через межі кадру.

Для цього необхідно перевірити клас об'єкта через

Object.prototype.toString.call(date) === '[object Date]'

28
З інтересу ви знаєте причину цього невдачі при переході меж кадру?
Саймон Лішке

85
@Simon: глобальні символи JS є локальними для поточного глобального об'єкта (ака windowчи self); різні кадри мають свої власні глобальні об'єкти, а їх властивості (тобто глобальні) посилаються на окремі об'єкти: Dateу frame1 - об'єкт функції іншої функції, ніж Dateу frame2; те саме стосується Date.prototype, що є причиною instanceofвідмови: Date.prototypefrom frame1 не входить до складу прототипу ланцюга Dateпримірників frame2
Крістоф

9
Крістофе, що ти називаєш "кадром"? IFRAME, кожен кадр у FRAMESET чи щось інше (я маю на увазі JS-специфічний, а не HTML-річ)?
Павло

12
new Date('something') instanceof Dateповертається trueв Chrome. Це не буде працювати тоді.
krillgar

12
Виявлення об'єкта типу дати (на відміну від звичайного Об'єкта або рядка) та перевірка об'єкта, який ви очікуєте як Дата, - це дві різні задачі. Існує ряд ситуацій, коли вхід до вашої функції може бути одним із кількох різних типів даних. У моєму випадку я можу довіряти, що будь-який об’єкт Date, який я отримую, є дійсним (він не надходить прямо від клієнта) Якщо перевірка викликає занепокоєння, ось публікація з низкою варіантів. stackoverflow.com/questions/1353684/…
Майкл Блекберн

125

Ви можете використовувати наступний код:

(myvar instanceof Date) // returns true or false

6
Чому це не прийнята чи більш прихильна відповідь? Проста перевірка, чи має дата властивість .getMonth, може спричинити помилковий позитив.
doremi

24
instanceof може викликати помилкові негативи, див. коментар Крістофа до його власної відповіді.
Марко Мар'яні

2
@doremi Ось демонстрація instanceofпомилкових негативних результатів: jsbin.com/vufufoq/edit?html,js,console
Boghyon Hoffmann

68

Для того, щоб перевірити, чи є значення дійсним типом стандартного об'єкта дати JS, ви можете використовувати цей предикат:

function isValidDate(date) {
  return date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date);
}
  1. dateперевіряє , чи не був параметр а falsy значення ( undefined, null, 0, ""і т.д ..)
  2. Object.prototype.toString.call(date)повертає власне рядкове подання даного типу об'єкта - У нашому випадку "[object Date]". Оскільки date.toString()переосмислює його батьківський метод , нам потрібно .callабо .applyметод зObject.prototype безпосередньо з якого ..
    • Обходить визначений користувачем тип об'єкта з тим самим іменем конструктора (наприклад: "Дата")
    • Працює в різних контекстах JS (наприклад, кадрів) на відміну відinstanceof або Date.prototype.isPrototypeOf.
  3. !isNaN(date)нарешті перевіряє, чи не було значення Invalid Date.

1
Нічого isNaNне можна використовувати для перевірки Date. Це якийсь рівень нежилості PHP.
Нік

@Nick дата, хоча число.
Йосія

@Josiah Ну, звичайно, прибравши всі контексти є відмітка про часу там: typeof Date.now() === "number", але: typeof new Date() === "object". Однак, більш реально, дата - це час і місце в просторі.
Нік

39

Функція є getMonth(), ні GetMonth().

У будь-якому випадку, ви можете перевірити, чи є об'єкт властивістю getMonth, зробивши це. Це не обов'язково означає, що об'єктом є дата, а будь-який об'єкт, який має властивість getMonth.

if (date.getMonth) {
    var month = date.getMonth();
}

3
Перевірте, чи можна if (date.getMonth && typeof date.getMonth === "function") {...}
телефонувати

20

Як було зазначено вище, перед його використанням, мабуть, найпростіше просто перевірити, чи функція існує. Якщо вам дійсно все одно, що це об’єкт Date, а не просто об’єкт з getMonth()функцією, спробуйте це:

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

Це створить або клон значення, якщо він є Date, або створить недійсну дату. Потім ви можете перевірити, чи не вказано значення нової дати чи ні.


1
Це працювало для мене, дякую. Однак якщо ви передасте одну цифру, наприклад 0 або 1, це трактує це як дійсну дату ... будь-які думки?
Рікардо Санчес

Правильно, @RicardoSanchez. Ви, ймовірно, хочете використовувати прийняту відповідь ( Object.prototype.toString.call(value) === '[object Date]'), якщо можливо, ви отримаєте номери. Метод у цій відповіді дійсно підказує, чи valueможна конвертувати в a Date.
бдук

18

Для всіх типів я приготував функцію прототипу Object. Можливо, вам це буде корисно

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

Тепер ви можете перевірити будь- який подібний тип:

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

[ Редагувати березень 2013 ] на основі прогресуючого розуміння це кращий метод:

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


8

Найкращий спосіб мене знайшов:

!isNaN(Date.parse("some date test"))
//
!isNaN(Date.parse("22/05/2001"))  // true
!isNaN(Date.parse("blabla"))  // false

Це не працює. Ваш справжній рядок насправді хибний, і питання про перевірку, чи об’єкт є об’єктом дати ...
Клінт

1
Відповідь @jspassov є більш точною, якщо рядок - це дата чи ні. Це я шукав. Дякую!!
Анант

Це найкраща відповідь, щоб просто перевірити, чи є рядок датою чи ні
Джеймс

3

Ви можете перевірити, чи існує функція, характерна для об'єкта Date:

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

3

Замість усіх обхідних шляхів можна скористатись такими:

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

Я зламав цей хак краще!


2

Також ви можете використовувати коротку форму

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

або щось подібне:

(toString.call(date)) == 'Date'

2

Я використовував набагато простіший спосіб, але не впевнений, доступний він лише в ES6 чи ні.

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"

Однак це не буде працювати з нульовим або невизначеним, оскільки у них немає конструктора.


Будь-який об'єкт, виготовлений на замовлення з назвою конструктора "Дата", також повертається, "Date"що є настільки ж ризикованим, як і лише перевірка наявності цього параметра getMonth.
Boghyon Hoffmann

2
@boghyon звучить так, як хто створює об'єкт із назвою конструктора вже заздалегідь встановленої стандартної бібліотеки Javascript, в першу чергу не дотримується кращих практик. Це було б так, як завантажити lodash, потім створити власний модуль lodash і очікувати, що речі спрацюють.
mjwrazor

1

Ця функція повернеться, trueякщо це дата або falseінше:

function isDate(myDate) {
    return myDate.constructor.toString().indexOf("Date") > -1;
} 

1
isDate(new (function AnythingButNotDate(){ })())повертаєтьсяtrue
Богйон Гофман


1

Підхід із використанням спробу / лову

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


0

Фактично дата буде типовою Object. Але ви можете перевірити, чи є в об'єкта getMonthметод і чи він може називатися.

function getFormatedDate(date) {
    if (date && date.getMonth && date.getMonth.call) {
       var month = date.getMonth();
    }
}

2
Відповідь Крістофа точніша. Наявність властивості "call" не обов'язково означає, що це функція!
Chetan Sastry

-1

Ми також можемо перевірити його за кодом нижче

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

введіть тут опис зображення


Конструктор function Date() {/*...*/}також Date. Тобто просто порівняння функції конструктора є занадто схильною до помилок, що часто призводить до помилкових позитивних результатів. Обхідний певний користувачем тип об'єкта з stackoverflow.com/a/44198641/5846045
Boghyon Хоффман

-1

Натхненний цією відповіддю , це рішення працює в моєму випадку (мені потрібно було перевірити, чи отримане від API значення є датою чи ні):

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

Таким чином, якщо це якась випадкова рядок, що надходить від клієнта або будь-який інший об'єкт, ви можете дізнатися, чи це об'єкт, подібний даті.


-2

Не могли ви просто використовувати

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

1
Ні, лише isValidметод об'єкта дати має метод
nikk wong

2
@grumpy @nikkwong Ні і ні. Стандартного об'єкта дати немає isValid. Тільки moment.js має такий API.
Boghyon Hoffmann
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.