數字和日期
本章介紹了用於處理和執行數字和日期計算的JavaScript概念、物件和函式。這包括使用以各種進位制(包括十進位制、二進位制和十六進位制)編寫的數字,以及使用全域性Math物件對數字執行各種數學運算。
數字
在JavaScript中,數字以雙精度64位二進位制格式IEEE 754(即,介於±2^−1022和±2^+1023之間的數字,或大約±10^−308到±10^+308,數值精度為53位)實現。最多±2^53 − 1的整數值可以精確表示。
除了能夠表示浮點數之外,number型別還有三個符號值:Infinity、-Infinity和NaN(非數字)。
另請參閱JavaScript資料型別和結構,以瞭解JavaScript中其他基本型別的上下文。
您可以使用四種類型的數字字面量:十進位制、二進位制、八進位制和十六進位制。
十進位制數
1234567890
42
十進位制字面量可以以零(0)開頭,後跟另一個十進位制數字,但如果前導0之後的數字都小於8,則該數字將被解釋為八進位制數。這被認為是遺留語法,並且以0為字首的數字字面量(無論解釋為八進位制還是十進位制),都會在嚴格模式中導致語法錯誤——因此,請改用0o字首。
0888 // 888 parsed as decimal
0777 // parsed as octal, 511 in decimal
二進位制數
二進位制數語法使用前導零,後跟小寫或大寫拉丁字母“B”(0b或0B)。如果0b之後的數字不是0或1,則會丟擲以下SyntaxError:“0b之後缺少二進位制數字”。
0b10000000000000000000000000000000 // 2147483648
0b01111111100000000000000000000000 // 2139095040
0B00000000011111111111111111111111 // 8388607
八進位制數
八進位制數的標準語法是以0o為字首。例如
0O755 // 493
0o644 // 420
八進位制數還有一個遺留語法——透過以零為字首:0644 === 420和"\045" === "%"。如果0之後的數字超出0到7的範圍,則該數字將被解釋為十進位制數。
const n = 0755; // 493
const m = 0644; // 420
嚴格模式禁止此八進位制語法。
十六進位制數
十六進位制數語法使用前導零,後跟小寫或大寫拉丁字母“X”(0x或0X)。如果0x之後的數字超出範圍(0123456789ABCDEF),則會丟擲以下SyntaxError:“識別符號緊跟在數字字面量之後開始”。
0xFFFFFFFFFFFFFFFFF // 295147905179352830000
0x123456789ABCDEF // 81985529216486900
0XA // 10
指數運算
0e-5 // 0
0e+5 // 0
5e1 // 50
175e-2 // 1.75
1e3 // 1000
1e-3 // 0.001
1E3 // 1000
Number 物件
內建的Number物件具有數值常量的屬性,例如最大值、非數字和無窮大。您不能更改這些屬性的值,您可以按以下方式使用它們
const biggestNum = Number.MAX_VALUE;
const smallestNum = Number.MIN_VALUE;
const infiniteNum = Number.POSITIVE_INFINITY;
const negInfiniteNum = Number.NEGATIVE_INFINITY;
const notANum = Number.NaN;
您始終如上所示引用預定義Number物件的屬性,而不是作為您自己建立的Number物件的屬性。
下表總結了Number物件的屬性。
| 屬性 | 描述 |
|---|---|
Number.MAX_VALUE |
可表示的最大正數(1.7976931348623157e+308) |
Number.MIN_VALUE |
可表示的最小正數(5e-324) |
Number.NaN |
特殊的“非數字”值 |
Number.NEGATIVE_INFINITY |
特殊的負無窮大值;溢位時返回 |
Number.POSITIVE_INFINITY |
特殊的正無窮大值;溢位時返回 |
Number.EPSILON |
1與大於1且可以表示為Number的最小值之間的差(2.220446049250313e-16) |
Number.MIN_SAFE_INTEGER |
JavaScript中的最小安全整數(−2^53 + 1,或−9007199254740991) |
Number.MAX_SAFE_INTEGER |
JavaScript中的最大安全整數(+2^53 − 1,或+9007199254740991) |
| 方法 | 描述 |
|---|---|
Number.parseFloat() |
解析字串引數並返回浮點數。與全域性parseFloat()函式相同。 |
Number.parseInt() |
解析字串引數並返回指定基數或基數的整數。與全域性parseInt()函式相同。 |
Number.isFinite() |
確定傳遞的值是否為有限數。 |
Number.isInteger() |
確定傳遞的值是否為整數。 |
Number.isNaN() |
確定傳遞的值是否為NaN。原始全域性isNaN()的更強大版本。 |
Number.isSafeInteger() |
確定提供的值是否為安全整數。 |
Number原型提供了用於以各種格式從Number物件檢索資訊的方法。下表總結了Number.prototype的方法。
| 方法 | 描述 |
|---|---|
toExponential() |
返回表示以指數表示法的數字的字串。 |
toFixed() |
返回表示以定點表示法的數字的字串。 |
toPrecision() |
返回表示以定點表示法指定精度的數字的字串。 |
Math 物件
內建的Math物件具有用於數學常量和函式的屬性和方法。例如,Math物件的PI屬性的值為π(3.141…),您將在應用程式中使用它,如下所示
Math.PI;
類似地,標準數學函式是Math的方法。這些包括三角函式、對數函式、指數函式和其他函式。例如,如果您想使用三角函式正弦,您可以編寫
Math.sin(1.56);
請注意,Math的所有三角方法都以弧度為單位接受引數。
下表總結了Math物件的方法。
| 方法 | 描述 |
|---|---|
abs() |
絕對值 |
sin(),cos(),tan() |
標準三角函式;引數以弧度為單位。 |
asin(),acos(),atan(),atan2() |
反三角函式;返回值以弧度為單位。 |
sinh(),cosh(),tanh() |
雙曲函式;引數為雙曲角。 |
asinh(),acosh(),atanh() |
反雙曲函式;返回值為雙曲角。 |
| 指數和對數函式。 | |
floor(),ceil() |
返回小於/大於或等於引數的最大/最小整數。 |
min(),max() |
返回作為引數的逗號分隔數字列表的最小值或最大值。 |
random() |
返回 0 到 1 之間的隨機數。 |
round(),fround(),trunc(), |
舍入和截斷函式。 |
sqrt(),cbrt(),hypot() |
平方根,立方根,平方引數和的平方根。 |
sign() |
數字的符號,指示數字是正數、負數還是零。 |
clz32(),imul() |
32 位二進位制表示中前導零位的數量。 兩個引數的類似 C 語言的 32 位乘法的結果。 |
與許多其他物件不同,您永遠不會建立自己的 Math 物件。您始終使用內建的 Math 物件。
BigInt
數值的一個缺點是它們只有 64 位。在實踐中,由於使用 IEEE 754 編碼,它們無法精確地表示大於 Number.MAX_SAFE_INTEGER(即 253 - 1)的任何整數。為了解決編碼二進位制資料以及與提供寬整數(如 i64(64 位整數)和 i128(128 位整數))的其他語言進行互操作的需求,JavaScript 還提供了另一種資料型別來表示任意大的整數:BigInt。
BigInt 可以定義為以 n 為字尾的整數字面量
const b1 = 123n;
// Can be arbitrarily large.
const b2 = -1234567890987654321n;
BigInt 也可以使用 BigInt 建構函式從數值或字串值構建。
const b1 = BigInt(123);
// Using a string prevents loss of precision, since long number
// literals don't represent what they seem like.
const b2 = BigInt("-1234567890987654321");
從概念上講,BigInt 只是一個任意長的位序列,它編碼一個整數。您可以安全地執行任何算術運算,而不會丟失精度或溢位/下溢。
const integer = 12 ** 34; // 4.9222352429520264e+36; only has limited precision
const bigint = 12n ** 34n; // 4922235242952026704037113243122008064n
與數字相比,BigInt 值在表示大整數時具有更高的精度;但是,它們不能表示浮點數。例如,除法將四捨五入為零
const bigintDiv = 5n / 2n; // 2n, because there's no 2.5 in BigInt
Math 函式不能用於 BigInt 值。有一個 開放提案 來過載某些 Math 函式(如 Math.max())以允許 BigInt 值。
在 BigInt 和數字之間進行選擇取決於您的用例和輸入的範圍。數字的精度應該能夠滿足大多數日常任務,而 BigInt 最適合處理二進位制資料。
Date 物件
JavaScript 沒有日期資料型別。但是,您可以使用 Date 物件及其方法在應用程式中處理日期和時間。Date 物件有大量用於設定、獲取和操作日期的方法。它沒有任何屬性。
JavaScript 處理日期的方式與 Java 類似。這兩種語言有許多相同日期方法,並且兩種語言都將日期儲存為自 1970 年 1 月 1 日午夜(UTC)以來的毫秒數,Unix 時間戳是自同一時刻以來的秒數。1970 年 1 月 1 日午夜(UTC)的時刻稱為 紀元。
Date 物件的範圍相對於紀元為 -100,000,000 天到 100,000,000 天。
要建立一個 Date 物件
const dateObjectName = new Date([parameters]);
其中 dateObjectName 是正在建立的 Date 物件的名稱;它可以是新物件或現有物件的屬性。
在不使用 new 關鍵字的情況下呼叫 Date 會返回一個表示當前日期和時間的字串。
前面語法中的 parameters 可以是以下任何一個
- 無:建立今天的日期和時間。例如,
today = new Date();。 - 表示日期的字串,有多種不同的形式。支援的確切形式因引擎而異,但始終支援以下形式:
YYYY-MM-DDTHH:mm:ss.sssZ。例如,xmas95 = new Date("1995-12-25")。如果您省略小時、分鐘或秒,則該值將設定為零。 - 一組表示年份、月份和日期的整數值。例如,
xmas95 = new Date(1995, 11, 25)。 - 一組表示年份、月份、日期、小時、分鐘和秒的整數值。例如,
xmas95 = new Date(1995, 11, 25, 9, 30, 0);。
Date 物件的方法
用於處理日期和時間的功能Date 物件方法分為以下幾大類
- "set" 方法,用於在
Date物件中設定日期和時間值。 - "get" 方法,用於從
Date物件獲取日期和時間值。 - "to" 方法,用於從
Date物件返回字串值。 - parse 和 UTC 方法,用於解析
Date字串。
使用 "get" 和 "set" 方法,您可以分別獲取和設定秒、分、時、月日、星期幾、月和年。有一個 getDay 方法返回星期幾,但沒有相應的 setDay 方法,因為星期幾是自動設定的。這些方法使用整數表示這些值,如下所示
- 秒和分:0 到 59
- 小時:0 到 23
- 日期:0(星期日)到 6(星期六)
- 日期:1 到 31(月日)
- 月份:0(一月)到 11(十二月)
- 年份:自 1900 年以來的年份
例如,假設您定義以下日期
const xmas95 = new Date("1995-12-25");
然後 xmas95.getMonth() 返回 11,而 xmas95.getFullYear() 返回 1995。
getTime 和 setTime 方法對於比較日期很有用。getTime 方法返回 Date 物件自紀元以來的毫秒數。
例如,以下程式碼顯示今年剩餘的天數
const today = new Date();
const endYear = new Date(1995, 11, 31, 23, 59, 59, 999); // Set day and month
endYear.setFullYear(today.getFullYear()); // Set year to this year
const msPerDay = 24 * 60 * 60 * 1000; // Number of milliseconds per day
let daysLeft = (endYear.getTime() - today.getTime()) / msPerDay;
daysLeft = Math.round(daysLeft); // Returns days left in the year
此示例建立一個名為 today 的 Date 物件,其中包含今天的日期。然後它建立一個名為 endYear 的 Date 物件並將年份設定為當前年份。然後,使用每天的毫秒數,它使用 getTime 計算 today 和 endYear 之間的天數,並四捨五入到整天的天數。
parse 方法對於將日期字串中的值分配給現有的 Date 物件很有用。例如,以下程式碼使用 parse 和 setTime 將日期值分配給 ipoDate 物件
const ipoDate = new Date();
ipoDate.setTime(Date.parse("Aug 9, 1995"));
示例
在以下示例中,函式 JSClock() 以數字時鐘的格式返回時間。
function JSClock() {
const time = new Date();
const hour = time.getHours();
const minute = time.getMinutes();
const second = time.getSeconds();
let temp = String(hour % 12);
if (temp === "0") {
temp = "12";
}
temp += (minute < 10 ? ":0" : ":") + minute;
temp += (second < 10 ? ":0" : ":") + second;
temp += hour >= 12 ? " P.M." : " A.M.";
return temp;
}
JSClock 函式首先建立一個名為 time 的新 Date 物件;由於沒有給出引數,因此 time 使用當前日期和時間建立。然後,對 getHours、getMinutes 和 getSeconds 方法的呼叫將當前小時、分鐘和秒的值分別分配給 hour、minute 和 second。
以下語句基於時間構建一個字串值。第一條語句建立一個變數 temp。它的值為 hour % 12,即 12 小時制中的 hour。然後,如果小時為 0,則將其重新分配為 12,以便將午夜和中午顯示為 12:00 而不是 0:00。
下一條語句將 minute 值附加到 temp。如果 minute 的值小於 10,則條件表示式新增一個帶有前導零的字串;否則,它新增一個帶有分隔符冒號的字串。然後,一條語句以相同的方式將秒值附加到 temp。
最後,一個條件表示式在 hour 大於或等於 12 時將 "P.M." 附加到 temp;否則,它將 "A.M." 附加到 temp。