Numbers and dates

Chương này giới thiệu những khái niệm, đối tượng và hàm được sử dụng để làm việc và tính toán với giá trị số và ngày tháng trong JavaScript. Nó bao gồm việc sử dụng những con số được viết dưới dạng những hệ cơ số khác nhau như là hệ thập phân, hệ nhị phân và hệ thập lục phân, cũng như việc sử dụng đối tượng toàn cục Math để thực hiện các phép toán số học.

Con Số (Numbers)

Trong JavaScript, tất cả các con số được cài đặt theo double-precision 64-bit binary format IEEE 754 (ví dụ: một số bắt đầu từ ±2−1022 and ±2+1023, hoặc là khoảng ±10−308 to ±10+308, với độ chính xác 53 bits sau dấu phẩy). Số nguyên lớn nhất có thể là ±253 − 1. Để có thể biểu diễn số thực dấu chấm động, ta có thể dùng ba ký hiệu +Infinity, -Infinity, and NaN (not-a-number). Xem thêm trong JavaScript data types and structures về những kiểu sơ cấp trong JavaScript.

Lưu Ý: Không có kiểu cụ thể cho số nguyên trong JavaScript, mặc dù kiểu BigInt cho phép biểu diễn số nguyên mà có giá trị rất lớn. Nhưng cần cẩn thận khi dùng BigInt, ví dụ, bạn có không thể kết hợp giá trị BigIntNumber trong cùng một biểu thức, và bạn cũng không thể sử dụng Math với giá trị BigInt.

Bạn có thể sử dụng bốn loại literal để tạo số: thập phân, nhị phân, bát phân và thập lục phân.

Số thập phân

1234567890
42

// Cẩn thận với số bắt đầu bằng số không:

0888 // 888 trong hệ thập phân
0777 // được xem như là số bát phân trong chế độ non-strict (và có giá trị là 511 trong hệ thập phân)

Lưu ý literal thập phân có thể bắt đầu bằng số zero (0) được theo sau là những số thập phân, nhưng nếu mọi chữ số sau số 0 nhỏ hơn 8, thì nó hiểu nhầm như là hệ bát phân.

Số nhị phân

Cú pháp của hệ nhị phân bắt đầu bằng chữ số 0 theo sau là "B" hoặc "b" (0b or 0B). Nếu các chữ số theo sau 0b không phải là 0 hoặc 1, thì lỗi  SyntaxError sẽ phát sinh như sau "Missing binary digits after 0b".

var FLT_SIGNBIT  = 0b10000000000000000000000000000000; // 2147483648
var FLT_EXPONENT = 0b01111111100000000000000000000000; // 2139095040
var FLT_MANTISSA = 0B00000000011111111111111111111111; // 8388607

Số bát phân

Số bát phân bắt đầu bằng số 0. Nếu chữ số theo sau số 0 không nắm trong khoảng từ 0 đến 7, thì số đó sẽ được hiểu là số thập phân.

var n = 0755; // 493
var m = 0644; // 420

Trong chế độ strict trong ECMAScript 5 ngăn cấm cú pháp hệ bát phân. Cú pháp hệ bát phân không nằm trong đặc tả của ECMAScript 5, nhưng nó được hỗ trợ bởi tất cả các trình duyệt bằng cách đặt tiền tố 0:  0644 === 420 and"\045" === "%". Trong ECMAScript 2015 (ES6), số bát phân được hỗ trợ nếu chúng bắt đầu bằng 0o, ví dụ:

var a = 0o10; // ES2015: 8

Số thập lục phân

Cú pháp của số thập lục phân được bắt đầu bằng 0 và theo sau là "x" hoặc "X" (0x or 0X). Nếu các chữ số theo sau 0x nằm ngoài khoảng giá trị  (0123456789ABCDEF), Lỗi  SyntaxError sẽ phát sinh: "Identifier starts immediately after numeric literal".

0xFFFFFFFFFFFFFFFFF // 295147905179352830000
0x123456789ABCDEF   // 81985529216486900
0XA                 // 10

Số mũ

1E3   // 1000
2e6   // 2000000
0.1e2 // 10

Number object

Number object có những thuộc tính có giá trị là những hằng kiểu số, như giá trị lớn nhất, not-a-number, và vô cực. Bạn không thể thay đổi những giá trị của những thuộc tính này và bạn sử dụng nó như sau:

var biggestNum = Number.MAX_VALUE;
var smallestNum = Number.MIN_VALUE;
var infiniteNum = Number.POSITIVE_INFINITY;
var negInfiniteNum = Number.NEGATIVE_INFINITY;
var notANum = Number.NaN;

Bạn luôn phải tham chiếu đến những thuộc tính được định nghĩa sẳn của Number object như trên, và không thể truy xuất qua giá trị số mà bạn tạo ra.

Bảng sau tổng hợp những thuộc tính của Number object.

Thuộc tính của Number
Thuộc tính Mô tả
Number.MAX_VALUE Số lớn nhất có thể gán (±1.7976931348623157e+308)
Number.MIN_VALUE Số nhỏ nhất có thể gán (±5e-324)
Number.NaN Special "not a number" value
Giá trị đặc biệt để mô tả "không phải là số"
Number.NEGATIVE_INFINITY Giá trị số âm vô định; được về khi vượt quá giá trị có thể tính toán
Number.POSITIVE_INFINITY Giá trị số dương vô định; được về khi vượt quá giá trị có thể tính toán
Number.EPSILON Sự khác nhau giữa 1 và giá trị nhỏ nhất lớn hơn 1 mà có thể được biểu diễn là một số
Number (2.220446049250313e-16)
Number.MIN_SAFE_INTEGER Số nguyên được an toàn nhỏ nhất trong JavaScript (−253 + 1, or −9007199254740991)
Number.MAX_SAFE_INTEGER Số nguyên dương an toàn lớn nhất trong JavaScript (+253 − 1, or +9007199254740991)
Phương thức của Number
Phương thức Mô tả
Number.parseFloat() Phân tích giá trị chuỗi và trả vể một giá trị số thực.
Giống như hàm toàn cục parseFloat().
Number.parseInt() Phân tích giá trị kiểu chuỗi và trả về giá trị số nguyên dựa trên cơ số chỉ định.
Cũng giống như hàm toàn cục parseInt() function.
Number.isFinite() Xác định giá trị được truyền vào có phải là một số xác đinh.
Number.isInteger() Xác định giá trị truyền vào có phải là một số nguyên.
Number.isNaN() Xác định giá trị truyền vào là NaN. Đây là phiên bản cải tiến của isNaN().
Number.isSafeInteger() Xác định giá trị truyền vào là một số nguyên an toàn.

Number prototype cung cấp những phương thức để lấy thông tin từ những đối tượng Number dưới nhiều định dạng. Bảng sau đây tổng hợp những phương thức của Number.prototype.

Những phương thức của Number.prototype
Phương thức Mô tả
toExponential() Trả về một chuỗi biểu diễn một số theo dạng lũy thừa.
toFixed() Trả về một chuỗi biểu diễn một số theo dạng số thập phân, với phần thập phân cố định.
toPrecision() Trả về một chuỗi biểu diễn một số thập phân với độ chính xác được chỉ định.

Math object

Math object cung cấp thuộc tính và những phương thức để lấy giá trị của các hằng số và những hàm toán học. Ví dụ, thuộc tính PI của Math có giá trị pi (3.141...), mà bạn có thể sử dụng trong ứng dụng như

Math.PI

Tương tự, những hàm chuẩn của toán học là phương thức của Math. Bao gồm lượng giác, logarit, hàm mũ, và những hàm khác nữa. Ví dụ, nếu bạn muốn sử dụng hàm lượng giác sine, bạn có thể viết như sau

Math.sin(1.56)

Lưu ý rằng phương thức lượng giác của Math nhận đổi số kiểu radians.

Bảng sau tóm tắt những phương thức của đối tượng Math.

Phương thức của Math
Phương thức Mô tả
abs() Giá trị tuyệt đối
sin(), cos(), tan() Những hàm lượng giác chuẩn, với đối số đơn vị radians.
asin(), acos(), atan(), atan2() Những hàm lượng giác ngược; trả về giá trị theo đơn vị radians.
sinh(), cosh(), tanh() Hàm Hyperbolic; đối số là giá trị theo đơn vị hyperbolic.
 
asinh(), acosh(), atanh() Nghịch đảo của hàm hyperbolic; đối số là giá trị theo đơn vị hyperbolic.

pow(), exp()expm1(), log10(), log1p(), log2()

Hàm mũ và hàm logarit
floor(), ceil() Trả về số nguyên lớn nhất và nhỏ nhất mà nhỏ hơn hoặc lớn hơn hoặc bằng đối số truyền vào.
min(), max() Trả về giá trị lớn nhất hoặc nhỏ nhất trong dãy các giá trị truyền vào.
random() Trả về số ngẫu nhiên trong khoảng 0 và 1.
round(), fround(), trunc(), Những hàm làm tròn hoặc cắt bớt.
sqrt(), cbrt(), hypot()

Căn bậc hai, cube root, căn bậc hai của tổng đối số bình phương.

sign() Xác dịnh số âm hay số dương hay số không
clz32(),
imul()
Số bit 0 ở đầu trong số nhị phân 32 bit. Kết quả của phép nhân 32 bit.

Không giống như những object khác, bạn không bao giờ tạo Math riêng. Bạn luôn dùng đối tượng Math có sẳn

Date object

JavaScript không có kiểu dữ liệu ngày tháng. Tuy nhiên, bạn có thể sử dụng Date object và phương thức của nó để làm việc với ngày giờ trong ứng dụng của mình. Date object cung cấp nhiều phương thức trực tiếp để thao tác trên trên giá trị ngày giờ. Nó không có bất kỳ thuộc tính nào.

JavaScript xử lý ngày giờ tương tự Java. Hai ngôn ngữ có nhiều tên phương thức giống nhau, và cả hai ngôn ngữ đều lưu trữ ngày giờ như là một số theo mili giây tính từ ngày 1 tháng 1 năm 1970, 00:00:00, với một Unix Timestamp là một số theo giây tính từ ngày 1 tháng 1, 1970, 00:00:00.

Dãy giá trị của Date object là -100,000,000 ngày đến 100,000,000 ngày so với 01 tháng 1, 1970 UTC.

Để tạo một Date object:

var dateObjectName = new Date([parameters]);

dateObjectName là biến lưu trữ Date object được  tạo;

Nếu chúng ta bỏ qua từ khóa new, giá trị nhận được là một chuỗi biểu diễn giá trị kiểu ngày giờ.

parameters trong cú pháp trên có thể là một trong những giá trị sau:

  • Không truyền gì vào: tạo ngày giờ hiện hành. Ví dụ: today = new Date();.
  • Một chuỗi biểu diễn ngày giờ theo định dạng: "Tháng ngày, năm giờ:phút:giây". Ví dụ: var Xmas95 = new Date("December 25, 1995 13:30:00"). Nếu bạn bỏ sót giờ, phút, giây, giá trị mặc định sẽ là 0.
  • Một tập các số nguyên cho năm, tháng, và ngày. Ví dụ, var Xmas95 = new Date(1995, 11, 25).
  • Một tập các số nguyên cho năm, tháng, ngày, giờ, phút, và giây. Ví dụ var Xmas95 = new Date(1995, 11, 25, 9, 30, 0);.

Những phương thức của Date object

Những phương thức của Date object để xử lý thuộc một trong những loại sau:

  • phương thức "set", để gán giá trị ngày giờ cho Date objects.
  • phương thức "get", để nhận giá trị ngày giờ từ Date objects.
  • phương thức "to", để nhận về giá trị kiểu chuỗi cho Date objects.
  • phương thức phân giải (parse) và UTC, để phân giải chuỗi Date .

Với phương thức "get" và "set" bạn có thể nhận và gán giây, phút, giờ và ngày của tháng, ngày của tuần, tháng, và năm. Phương thức getDay trả về ngày của tuần, tháng, nhưng không có phương thức setDay tương ứng, bởi vì ngày của tuần được xác định tự động. Những phương thức này sử dụng số nguyên để biểu diễn những giá trị sau:

  • Giây và phúc: 0 đến 59
  • Giờ: 0 đến 23
  • Thứ: 0 (Chủ nhật) đến 6 (Thứ bảy)
  • Ngày: 1 đến 31 (ngày của tháng)
  • Tháng: 0 (Tháng 1) to 11 (Tháng 12)
  • Năm: năm tính từ 1900

Ví dụ, giả sử bạn định nghĩa giá trị ngày như sau:

var Xmas95 = new Date('December 25, 1995');

Phương thức Xmas95.getMonth() trả về 11, và Xmas95.getFullYear() trả về 1995.

Phương thức getTimesetTime dùng để so sánh hai giá trị ngày. Phương thức getTime trả về số milli giây tính từ 0 giờ 0 phút 0 giây ngày 1 tháng 1 năm 1970.

Ví dụ đoạn mã sau hiển thị số ngày còn lại trong năm hiện tại:

var today = new Date();
var endYear = new Date(1995, 11, 31, 23, 59, 59, 999); // Set day and month
endYear.setFullYear(today.getFullYear()); // Set year to this year
var msPerDay = 24 * 60 * 60 * 1000; // Number of milliseconds per day
var daysLeft = (endYear.getTime() - today.getTime()) / msPerDay;
var daysLeft = Math.round(daysLeft); //returns days left in the year

Đầu tiên một Date object được tạo ra với tên là today chứ giá trị là ngày hiện tại. Sau đó, một Date object nữa được tạo ra với tên là endYear và được gán giá trị của ngày cuối cùng của năm 1995. Nhưng sau đó endYear được gán lại với năm hiện tại cho đồng nhất về năm. Rồi ta tính toán độ chênh lệch theo ngày giữa endYeartoday giá trị phải được làm tròn.

Phương thức parse dùng để chuyển đổi chuỗi kiểu  Date thành Date object. Ví dụ, Đoạn mã sau sử dụng parsesetTime để gán giá trị ngày cho biến IPOdate:

var IPOdate = new Date();
IPOdate.setTime(Date.parse('Aug 9, 1995'));

Ví dụ

Trong ví dụ sau, hàm JSClock() trả về thời gian trong định dạng của đồng hồ số.

function JSClock() {
  var time = new Date();
  var hour = time.getHours();
  var minute = time.getMinutes();
  var second = time.getSeconds();
  var temp = '' + ((hour > 12) ? hour - 12 : hour);
  if (hour == 0)
    temp = '12';
  temp += ((minute < 10) ? ':0' : ':') + minute;
  temp += ((second < 10) ? ':0' : ':') + second;
  temp += (hour >= 12) ? ' P.M.' : ' A.M.';
  return temp;
}

Hàm JSClock đầu tiên tạo ra Date object với tên time; vì không có đối số được cung cấp, time được tạo ra có giá trị là ngày giờ hiện tại. Sau đó các hàm getHours, getMinutes, và getSeconds để gán giá trị giờ, phút, giây hiện tai cho các biến hour, minute, và second.

Bốn câu lệnh kế tiếp tạo giá trị chuỗi từ thời gian. Câu lệnh đầu tiên tạo một biến temp, dùng biểu thức điều kiện để gán 1 giá trị cho temp; nếu hour lớn hơn 12, thì gán (hour - 12), ngược lại thì gán giá trị của hour.  Nếu giá trị của hour là 0, thì giá trị 12 cho temp.

Câu lệnh tiếp theo chèn gía trị minute cho temp. Nếu giá trị của minute kém hơn 10, ta thêm ':0' vào trước giá trị chuỗi; ngược lại ta chỉ thêm ':'. Sau đó chèn giá trị giây vào temp với cùng cách trên.

Cuối cùng, chèn "P.M" vào temp nếu hour lớn hơn 12, ngược lại ta chèn "A.M.".