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


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.