Làm thế nào để kiểm tra xem một đối tượng là một ngày?


601

Tôi có một lỗi khó chịu trên một trang web:

date.GetMonth () không phải là một hàm

Vì vậy, tôi cho rằng tôi đang làm gì đó sai. Biến datekhông phải là một đối tượng của loại Date. Làm cách nào tôi có thể kiểm tra kiểu dữ liệu trong Javascript? Tôi đã cố gắng thêm một if (date), nhưng nó không hoạt động.

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

Vì vậy, nếu tôi muốn viết mã phòng thủ và ngăn ngày (không phải là một) được định dạng, tôi phải làm thế nào?

Cảm ơn!

CẬP NHẬT: Tôi không muốn kiểm tra định dạng của ngày, nhưng tôi muốn chắc chắn rằng tham số được truyền cho phương thức getFormatedDate()là loại Date.


Trong trường hợp cũng nên xác thực xem ngày đó không phải là Invalid Date: stackoverflow.com/a/44198641/5846045
Boghyon Hoffmann

Câu trả lời:


1109

Thay thế cho việc gõ vịt qua

typeof date.getMonth === 'function'

bạn có thể sử dụng instanceoftoán tử, tức là Nhưng nó cũng sẽ trả về true cho các ngày không hợp lệ, ví dụ: new Date('random_string')cũng là ví dụ của Date

date instanceof Date

Điều này sẽ thất bại nếu các đối tượng được vượt qua ranh giới khung.

Cách khắc phục cho việc này là kiểm tra lớp của đối tượng thông qua

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

28
Không quan tâm bạn có biết lý do cho sự thất bại này khi vượt qua các ranh giới khung không?
Simon Lieschke

85
@Simon: Toàn cầu JS là cục bộ của đối tượng toàn cầu hiện tại (aka windowhoặc self); các khung khác nhau có các đối tượng toàn cầu riêng và các thuộc tính của chúng (tức là toàn cục) đề cập đến các đối tượng riêng biệt: Datetrong frame1 là một đối tượng chức năng khác với Datetrong frame2; điều tương tự cũng đúng Date.prototype, đó là lý do cho sự instanceofthất bại: Date.prototypetừ frame1 không phải là một phần của chuỗi các Datetrường hợp nguyên mẫu từ frame2
Christoph

9
Christoph, bạn gọi "khung" là gì? IFRAME, mỗi khung hình trong FRAMEET hoặc một cái gì đó khác (ý ​​tôi là cụ thể về JS, không phải là thứ HTML)?
Paul

12
new Date('something') instanceof Datetrả lại truetrong Chrome. Điều đó sẽ không làm việc sau đó.
krillgar

12
Phát hiện một đối tượng loại Ngày (trái ngược với Đối tượng đơn giản hoặc chuỗi) và xác thực một đối tượng mà bạn mong đợi là Ngày là hai nhiệm vụ khác nhau. Có một số tình huống trong đó đầu vào cho chức năng của bạn có thể là một trong một số loại dữ liệu khác nhau. Trong trường hợp của tôi, tôi có thể tin tưởng rằng bất kỳ đối tượng Ngày nào tôi nhận được đều hợp lệ (nó không đến trực tiếp từ khách hàng) Nếu xác thực là một mối quan tâm, đây là một bài đăng với một số tùy chọn. stackoverflow.com/questions/1353684/ Mạnh
Michael Blackburn

125

Bạn có thể sử dụng mã sau đây:

(myvar instanceof Date) // returns true or false

6
Tại sao đây không phải là câu trả lời được chấp nhận hoặc nâng cao hơn? Chỉ cần kiểm tra xem ngày có thuộc tính .getMonth có thể kích hoạt dương tính giả hay không.
doremi

24
dụof có thể kích hoạt phủ định sai, xem bình luận của Christoph cho câu trả lời của riêng mình.
Marco Mariani

2
@doremi Đây là bản demo instanceofkích hoạt âm tính giả: jsbin.com/vufufoq/edit?html,js,console
Boghyon Hoffmann

68

Để kiểm tra xem giá trị có phải là loại hợp lệ của đối tượng ngày JS tiêu chuẩn hay không, bạn có thể sử dụng vị từ này:

function isValidDate(date) {
  return date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date);
}
  1. datekiểm tra xem các thông số không phải là một giá trị falsy ( undefined, null, 0, "", vv ..)
  2. Object.prototype.toString.call(date)trả về một đại diện chuỗi gốc của loại đối tượng đã cho - Trong trường hợp của chúng tôi "[object Date]". Bởi vì date.toString()ghi đè phương thức cha của nó , chúng ta cần .callhoặc .applyphương thức Object.prototypetrực tiếp ..
  3. !isNaN(date)cuối cùng kiểm tra xem giá trị không phải là một Invalid Date.

1
Wow isNaNcó thể được sử dụng để kiểm tra a Date. Đó là một mức độ vô tri của PHP.
Nick

@Nick một ngày là một số mặc dù.
Giô

@Josiah Vâng, chắc chắn, xóa tất cả bối cảnh có dấu thời gian ở đó : typeof Date.now() === "number", nhưng : typeof new Date() === "object". Thực tế hơn, mặc dù, một ngày là một thời gian và một vị trí trong không gian.
Nick

39

Các chức năng là getMonth(), không GetMonth().

Dù sao, bạn có thể kiểm tra xem đối tượng có thuộc tính getMonth hay không bằng cách thực hiện việc này. Điều đó không nhất thiết có nghĩa là đối tượng là Ngày, chỉ là bất kỳ đối tượng nào có thuộc tính getMonth.

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

3
Kiểm tra xem nó có thể gọi được không:if (date.getMonth && typeof date.getMonth === "function") {...}
Aloso

20

Như đã chỉ ra ở trên, có lẽ dễ dàng nhất là chỉ kiểm tra xem hàm có tồn tại trước khi sử dụng không. Nếu bạn thực sự quan tâm rằng đó là một Date, và không chỉ là một đối tượng có getMonth()chức năng, hãy thử điều này:

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

Điều này sẽ tạo một bản sao của giá trị nếu đó là một Datehoặc tạo một ngày không hợp lệ. Sau đó, bạn có thể kiểm tra xem giá trị của ngày mới có hợp lệ hay không.


1
Điều này làm việc cho tôi, cảm ơn. Tuy nhiên, nếu bạn vượt qua một chữ số duy nhất như 0 hoặc 1, nó sẽ coi đó là Ngày hợp lệ ... bạn có suy nghĩ gì không?
Ricardo Sanchez

Đúng vậy, @RicardoSanchez. Bạn có thể muốn sử dụng câu trả lời được chấp nhận ( Object.prototype.toString.call(value) === '[object Date]') nếu có thể bạn sẽ nhận được số. Phương pháp trong câu trả lời này thực sự cho bạn biết liệu valuecó thể chuyển đổi thành a Date.
bdukes

18

Đối với tất cả các loại tôi đã tạo ra một hàm nguyên mẫu Object. Nó có thể được sử dụng cho bạn

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

Bây giờ bạn có thể kiểm tra bất kỳ loại như thế này:

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

[ Chỉnh sửa tháng 3 năm 2013 ] dựa trên hiểu biết tiến bộ, đây là một phương pháp tốt hơn:

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

Cách tốt nhất tôi tìm thấy là:

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

Điều này không hoạt động. Dòng thực sự của bạn thực sự là sai và câu hỏi là về việc kiểm tra xem một đối tượng có phải là đối tượng ngày không ...
Clint

1
Câu trả lời @jspassov chính xác hơn với việc một chuỗi có phải là ngày hay không. Điều đó tôi đang tìm kiếm. Cảm ơn!!
Anant

Đây là câu trả lời tốt nhất cho việc đơn giản kiểm tra xem một chuỗi có phải là một ngày hay không
James Gentes

3

Bạn có thể kiểm tra xem một hàm cụ thể cho đối tượng Date có tồn tại không:

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

3

Thay vì tất cả các cách giải quyết, bạn có thể sử dụng như sau:

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

Tôi thấy hack này tốt hơn!


2

Ngoài ra, bạn có thể sử dụng mẫu ngắn

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

hoặc thứ gì đó giống thế này:

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

2

Tôi đã sử dụng một cách đơn giản hơn nhiều nhưng không chắc điều này có sẵn trong ES6 hay không.

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"

Tuy nhiên, điều này sẽ không hoạt động trên null hoặc không xác định vì chúng không có hàm tạo.


Bất kỳ đối tượng được thực hiện tùy chỉnh nào có tên hàm tạo "Ngày" "Date"cũng trả về rủi ro như việc kiểm tra xem tham số có thuộc getMonthtính không.
Boghyon Hoffmann

2
@boghyon nghe có vẻ như bất cứ ai tạo ra một đối tượng với tên hàm tạo của thư viện chuẩn Javascript đã được xác định trước không tuân theo các thực tiễn tốt nhất ở vị trí đầu tiên. Điều đó sẽ giống như tải xuống lodash sau đó tạo mô-đun lodash của riêng bạn và mong muốn mọi thứ hoạt động.
mjwrazor

1

Chức năng này sẽ trở lại truenếu là Ngày hoặc theo falsecách khác:

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

1
isDate(new (function AnythingButNotDate(){ })())trở lạitrue
Boghyon Hoffmann

1

Một biến thể khác:

Date.prototype.isPrototypeOf(myDateObject)

Đẹp và ngắn! Nhưng thật không may, nó có cùng một vấn đề nhưinstanceof .
Boghyon Hoffmann

@BoghyonHoffmann trong trường hợp của iFrame, nó có thể trông giống như: iWindow.Date.prototype.isPrototypeOf(iWindow.date); // true iWindow.date instanceof iWindow.Date; // true
Vadim

1

Cách tiếp cận bằng cách sử dụng thử / bắt

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

Trên thực tế ngày sẽ là loại Object. Nhưng bạn có thể kiểm tra xem đối tượng có getMonthphương thức không và liệu nó có thể gọi được không.

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

2
Câu trả lời của Christoph chính xác hơn. Có một thuộc tính 'cuộc gọi' không nhất thiết có nghĩa là nó là một chức năng!
Chetan Sastry

-1

Chúng tôi cũng có thể xác nhận nó bằng mã bên dưới

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

nhập mô tả hình ảnh ở đây


Các nhà xây dựng của function Date() {/*...*/}cũng là Date. Tức là chỉ đơn giản là so sánh hàm xây dựng quá dễ bị lỗi, điều này thường dẫn đến kết quả dương tính giả. Bỏ qua loại đối tượng do người dùng xác định với stackoverflow.com/a/44198641/5846045
Boghyon Hoffmann

-1

Lấy cảm hứng từ câu trả lời này , giải pháp này hoạt động trong trường hợp của tôi (tôi cần kiểm tra xem giá trị nhận được từ API có phải là ngày hay không):

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

Theo cách này, nếu đó là một chuỗi ngẫu nhiên đến từ máy khách hoặc bất kỳ đối tượng nào khác, bạn có thể tìm hiểu xem đó có phải là một đối tượng giống như Ngày không.


-2

Bạn không thể sử dụng

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

1
Không, chỉ có đối tượng ngày có isValidphương thức
nikk wong

2
@grumpy @nikkwong Không và không. Đối tượng ngày tiêu chuẩn không có isValid. Chỉ khoảnh khắc.js mới có API như vậy.
Boghyon Hoffmann
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.