數字和日期

本章介紹了用於處理和執行數字和日期計算的JavaScript概念、物件和函式。這包括使用以各種進位制(包括十進位制、二進位制和十六進位制)編寫的數字,以及使用全域性Math物件對數字執行各種數學運算。

數字

在JavaScript中,數字以雙精度64位二進位制格式IEEE 754(即,介於±2^−1022和±2^+1023之間的數字,或大約±10^−308到±10^+308,數值精度為53位)實現。最多±2^53 − 1的整數值可以精確表示。

除了能夠表示浮點數之外,number型別還有三個符號值:Infinity-InfinityNaN(非數字)。

另請參閱JavaScript資料型別和結構,以瞭解JavaScript中其他基本型別的上下文。

您可以使用四種類型的數字字面量:十進位制、二進位制、八進位制和十六進位制。

十進位制數

js
1234567890
42

十進位制字面量可以以零(0)開頭,後跟另一個十進位制數字,但如果前導0之後的數字都小於8,則該數字將被解釋為八進位制數。這被認為是遺留語法,並且以0為字首的數字字面量(無論解釋為八進位制還是十進位制),都會在嚴格模式中導致語法錯誤——因此,請改用0o字首。

js
0888 // 888 parsed as decimal
0777 // parsed as octal, 511 in decimal

二進位制數

二進位制數語法使用前導零,後跟小寫或大寫拉丁字母“B”(0b0B)。如果0b之後的數字不是0或1,則會丟擲以下SyntaxError:“0b之後缺少二進位制數字”。

js
0b10000000000000000000000000000000 // 2147483648
0b01111111100000000000000000000000 // 2139095040
0B00000000011111111111111111111111 // 8388607

八進位制數

八進位制數的標準語法是以0o為字首。例如

js
0O755 // 493
0o644 // 420

八進位制數還有一個遺留語法——透過以零為字首:0644 === 420"\045" === "%"。如果0之後的數字超出0到7的範圍,則該數字將被解釋為十進位制數。

js
const n = 0755; // 493
const m = 0644; // 420

嚴格模式禁止此八進位制語法。

十六進位制數

十六進位制數語法使用前導零,後跟小寫或大寫拉丁字母“X”(0x0X)。如果0x之後的數字超出範圍(0123456789ABCDEF),則會丟擲以下SyntaxError:“識別符號緊跟在數字字面量之後開始”。

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

指數運算

js
0e-5   // 0
0e+5   // 0
5e1    // 50
175e-2 // 1.75
1e3    // 1000
1e-3   // 0.001
1E3    // 1000

Number 物件

內建的Number物件具有數值常量的屬性,例如最大值、非數字和無窮大。您不能更改這些屬性的值,您可以按以下方式使用它們

js
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…),您將在應用程式中使用它,如下所示

js
Math.PI;

類似地,標準數學函式是Math的方法。這些包括三角函式、對數函式、指數函式和其他函式。例如,如果您想使用三角函式正弦,您可以編寫

js
Math.sin(1.56);

請注意,Math的所有三角方法都以弧度為單位接受引數。

下表總結了Math物件的方法。

Math的方法
方法 描述
abs() 絕對值
sin()cos()tan() 標準三角函式;引數以弧度為單位。
asin()acos()atan()atan2() 反三角函式;返回值以弧度為單位。
sinh()cosh()tanh() 雙曲函式;引數為雙曲角。
asinh()acosh()atanh() 反雙曲函式;返回值為雙曲角。

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

指數和對數函式。
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 為字尾的整數字面量

js
const b1 = 123n;
// Can be arbitrarily large.
const b2 = -1234567890987654321n;

BigInt 也可以使用 BigInt 建構函式從數值或字串值構建。

js
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 只是一個任意長的位序列,它編碼一個整數。您可以安全地執行任何算術運算,而不會丟失精度或溢位/下溢。

js
const integer = 12 ** 34; // 4.9222352429520264e+36; only has limited precision
const bigint = 12n ** 34n; // 4922235242952026704037113243122008064n

與數字相比,BigInt 值在表示大整數時具有更高的精度;但是,它們不能表示浮點數。例如,除法將四捨五入為零

js
const bigintDiv = 5n / 2n; // 2n, because there's no 2.5 in BigInt

Math 函式不能用於 BigInt 值。有一個 開放提案 來過載某些 Math 函式(如 Math.max())以允許 BigInt 值。

在 BigInt 和數字之間進行選擇取決於您的用例和輸入的範圍。數字的精度應該能夠滿足大多數日常任務,而 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 物件

js
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 年以來的年份

例如,假設您定義以下日期

js
const xmas95 = new Date("1995-12-25");

然後 xmas95.getMonth() 返回 11,而 xmas95.getFullYear() 返回 1995。

getTimesetTime 方法對於比較日期很有用。getTime 方法返回 Date 物件自紀元以來的毫秒數。

例如,以下程式碼顯示今年剩餘的天數

js
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

此示例建立一個名為 todayDate 物件,其中包含今天的日期。然後它建立一個名為 endYearDate 物件並將年份設定為當前年份。然後,使用每天的毫秒數,它使用 getTime 計算 todayendYear 之間的天數,並四捨五入到整天的天數。

parse 方法對於將日期字串中的值分配給現有的 Date 物件很有用。例如,以下程式碼使用 parsesetTime 將日期值分配給 ipoDate 物件

js
const ipoDate = new Date();
ipoDate.setTime(Date.parse("Aug 9, 1995"));

示例

在以下示例中,函式 JSClock() 以數字時鐘的格式返回時間。

js
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 使用當前日期和時間建立。然後,對 getHoursgetMinutesgetSeconds 方法的呼叫將當前小時、分鐘和秒的值分別分配給 hourminutesecond

以下語句基於時間構建一個字串值。第一條語句建立一個變數 temp。它的值為 hour % 12,即 12 小時制中的 hour。然後,如果小時為 0,則將其重新分配為 12,以便將午夜和中午顯示為 12:00 而不是 0:00

下一條語句將 minute 值附加到 temp。如果 minute 的值小於 10,則條件表示式新增一個帶有前導零的字串;否則,它新增一個帶有分隔符冒號的字串。然後,一條語句以相同的方式將秒值附加到 temp

最後,一個條件表示式在 hour 大於或等於 12 時將 "P.M." 附加到 temp;否則,它將 "A.M." 附加到 temp