什么是 Math 对象

Math 是 JavaScript 内置的一个全局对象,它提供了各种数学常数和函数。注意:Math 不是构造函数 ,你不能使用 new Math() 来创建实例,所有属性和方法都是静态的,直接通过 Math.属性名Math.方法名() 调用。

javascript 复制代码
// ❌ 错误用法
const math = new Math();

// ✅ 正确用法
Math.PI; // 访问常量
Math.random(); // 调用方法

常用数学常量

Math 对象提供了一些常用的数学常量:

常量 说明
Math.PI 圆周率 π 3.141592653589793
Math.E 自然对数的底数 e 2.718281828459045
Math.LN2 2 的自然对数 0.6931471805599453
Math.LN10 10 的自然对数 2.302585092994046
Math.SQRT2 2 的平方根 1.4142135623730951

使用示例:

javascript 复制代码
// 计算圆的面积
function circleArea(radius) {
  return Math.PI * radius * radius;
}

console.log(circleArea(5)); // 78.53981633974483

常用数学方法

取整相关

1. Math.ceil() - 向上取整

返回大于或等于给定数字的最小整数(向正无穷方向舍入)。

javascript 复制代码
Math.ceil(4.1); // 5
Math.ceil(4.9); // 5
Math.ceil(-4.1); // -4
Math.ceil(4); // 4

应用场景: 计算文件分片数量时,即使最后一块不满,也需要单独作为一个分片。

javascript 复制代码
// 文件大小 1025 bytes,每片 1024 bytes
const fileSize = 1025;
const chunkSize = 1024;
const totalChunks = Math.ceil(fileSize / chunkSize); // 2 个分片
2. Math.floor() - 向下取整

返回小于或等于给定数字的最大整数(向负无穷方向舍入)。

javascript 复制代码
Math.floor(4.1); // 4
Math.floor(4.9); // 4
Math.floor(-4.1); // -5
Math.floor(4); // 4

应用场景: 将秒数转换为分钟和秒。

javascript 复制代码
const durationInSeconds = 125;
const minutes = Math.floor(durationInSeconds / 60); // 2 分钟
const seconds = durationInSeconds % 60; // 5 秒
console.log(`${minutes}:${seconds}`); // "2:5"
3. Math.round() - 四舍五入

返回最接近给定数字的整数(遵循四舍五入规则)。

javascript 复制代码
Math.round(4.4); // 4
Math.round(4.5); // 5
Math.round(4.6); // 5
Math.round(-4.5); // -4 (注意:-4.5 四舍五入为 -4)

应用场景: 视频时长显示时进行四舍五入。

javascript 复制代码
const videoDuration = 125.7;
const roundedDuration = Math.round(videoDuration); // 126 秒
4. Math.trunc() - 截断小数部分

移除数字的小数部分,只保留整数部分(不四舍五入)。

javascript 复制代码
Math.trunc(4.9); // 4
Math.trunc(-4.9); // -4
Math.trunc(4.1); // 4

区别对比:

javascript 复制代码
Math.floor(-4.5); // -5 (向下取整)
Math.trunc(-4.5); // -4 (截断小数)

最值相关

1. Math.max() - 最大值

返回一组数字中的最大值。

javascript 复制代码
Math.max(1, 5, 3, 9, 2); // 9
Math.max(-1, -5, -3); // -1

// 从数组中获取最大值
const numbers = [1, 5, 3, 9, 2];
Math.max(...numbers); // 9

应用场景: 确保滚动位置不小于 0。

javascript 复制代码
// 防止向左滚动超出边界
const scrollLeft = Math.max(0, scrollX - 200);
2. Math.min() - 最小值

返回一组数字中的最小值。

javascript 复制代码
Math.min(1, 5, 3, 9, 2); // 1
Math.min(-1, -5, -3); // -5

// 从数组中获取最小值
const numbers = [1, 5, 3, 9, 2];
Math.min(...numbers); // 1

应用场景: 限制读取的文件字节范围不超过文件总大小。

javascript 复制代码
const start = 0;
const chunkSize = 1024;
const fileSize = 500;
const end = Math.min(start + chunkSize, fileSize); // 500(不会超出文件大小)

随机数

Math.random() - 生成随机数

返回一个介于 0(包含)和 1(不包含)之间的伪随机浮点数。

javascript 复制代码
Math.random(); // 例如:0.7234567890123456

常用技巧:

javascript 复制代码
// 生成 0 到 n-1 之间的随机整数
const randomInt = Math.floor(Math.random() * 10); // 0-9

// 生成 min 到 max 之间的随机整数(包含 min 和 max)
function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

getRandomInt(1, 100); // 1-100 之间的随机整数

// 生成随机颜色
function getRandomColor() {
  const r = Math.floor(Math.random() * 256);
  const g = Math.floor(Math.random() * 256);
  const b = Math.floor(Math.random() * 256);
  return `rgb(${r}, ${g}, ${b})`;
}

幂运算与开方

1. Math.pow() - 幂运算

返回底数的指数次幂。

javascript 复制代码
Math.pow(2, 3); // 8 (2³)
Math.pow(5, 2); // 25 (5²)
Math.pow(2, -1); // 0.5 (2⁻¹)

// ES6 推荐使用指数运算符 **
2 ** 3; // 8
2. Math.sqrt() - 平方根

返回一个数的平方根。

javascript 复制代码
Math.sqrt(9); // 3
Math.sqrt(2); // 1.4142135623730951
Math.sqrt(-1); // NaN(负数没有实数平方根)

应用场景: 计算两点之间的距离。

javascript 复制代码
function distance(x1, y1, x2, y2) {
  return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}

distance(0, 0, 3, 4); // 5

绝对值

Math.abs() - 绝对值

返回一个数的绝对值(非负值)。

javascript 复制代码
Math.abs(5); // 5
Math.abs(-5); // 5
Math.abs(0); // 0
Math.abs(-3.14); // 3.14

应用场景: 计算差值的绝对值,不考虑正负。

javascript 复制代码
// 计算两个时间的差值(毫秒)
const timeDiff = Math.abs(timestamp1 - timestamp2);

实际应用场景

文件分片上传

在前端大文件上传场景中,需要将文件分割成多个小块进行上传:

javascript 复制代码
/**
 * 将文件分割成多个 chunk
 * @param {File} file - 要上传的文件
 * @param {number} chunkSize - 每个分片的大小(字节)
 * @returns {Array} 分片数组
 */
function splitFileIntoChunks(file, chunkSize = 1024 * 1024) {
  // 默认 1MB
  const totalChunks = Math.ceil(file.size / chunkSize);
  const chunks = [];

  for (let i = 0; i < totalChunks; i++) {
    const start = i * chunkSize;
    const end = Math.min(start + chunkSize, file.size);
    const chunk = file.slice(start, end);
    chunks.push({
      index: i,
      blob: chunk,
      size: chunk.size,
    });
  }

  return chunks;
}

// 使用示例
const file = document.querySelector('input[type="file"]').files[0];
const chunks = splitFileIntoChunks(file, 2 * 1024 * 1024); // 2MB 每片
console.log(`文件将被分成 ${chunks.length} 个分片`);

关键点:

  • 使用 Math.ceil() 确保即使最后一个分片不满,也会被计入
  • 使用 Math.min() 确保最后一个分片不会超出文件总大小

时间格式化

将时间戳或秒数转换为可读的时间格式:

javascript 复制代码
/**
 * 将秒数转换为 "mm:ss" 格式
 * @param {number} seconds - 秒数
 * @returns {string} 格式化后的时间字符串
 */
function formatTime(seconds) {
  const mins = Math.floor(seconds / 60);
  const secs = Math.floor(seconds % 60);
  return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
}

// 使用示例
console.log(formatTime(125)); // "02:05"
console.log(formatTime(65)); // "01:05"
console.log(formatTime(3661)); // "61:01"

更复杂的时间格式化:

javascript 复制代码
/**
 * 将秒数转换为 "hh:mm:ss" 格式
 */
function formatTimeHMS(seconds) {
  const hours = Math.floor(seconds / 3600);
  const mins = Math.floor((seconds % 3600) / 60);
  const secs = Math.floor(seconds % 60);

  if (hours > 0) {
    return `${hours}:${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
  }
  return `${mins}:${secs.toString().padStart(2, "0")}`;
}

console.log(formatTimeHMS(3661)); // "1:01:01"
console.log(formatTimeHMS(125)); // "2:05"

视频时长转换

处理视频元数据时,经常需要转换时长格式:

javascript 复制代码
/**
 * 将视频时长(秒)转换为人类可读的格式
 * @param {number} durationInSeconds - 视频时长(秒)
 * @returns {string} 格式化后的时长
 */
function formatVideoDuration(durationInSeconds) {
  const duration = Math.round(durationInSeconds); // 四舍五入
  const minutes = Math.floor(duration / 60);
  const seconds = duration % 60;

  if (minutes >= 60) {
    const hours = Math.floor(minutes / 60);
    const remainingMinutes = minutes % 60;
    return `${hours}:${remainingMinutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
  }

  return `${minutes}:${seconds.toString().padStart(2, "0")}`;
}

// 使用示例
console.log(formatVideoDuration(125.7)); // "2:06"
console.log(formatVideoDuration(3661.3)); // "1:01:01"
console.log(formatVideoDuration(59.4)); // "1:00"

滚动位置计算

在处理页面滚动、元素定位时,需要确保坐标值在合理范围内:

javascript 复制代码
/**
 * 计算安全的滚动位置
 * @param {number} currentScroll - 当前滚动位置
 * @param {number} offset - 偏移量
 * @param {number} maxScroll - 最大可滚动距离
 * @returns {number} 安全的滚动位置
 */
function getSafeScrollPosition(currentScroll, offset, maxScroll) {
  const targetScroll = currentScroll + offset;
  // 确保滚动位置在 0 到 maxScroll 之间
  return Math.max(0, Math.min(targetScroll, maxScroll));
}

// 使用示例
const currentScrollX = 500;
const scrollOffset = -200;
const maxScrollX = 1000;

const safeScroll = getSafeScrollPosition(
  currentScrollX,
  scrollOffset,
  maxScrollX,
);
console.log(safeScroll); // 300

// 边界情况
console.log(getSafeScrollPosition(100, -200, 1000)); // 0(不会小于 0)
console.log(getSafeScrollPosition(900, 200, 1000)); // 1000(不会超过最大值)

实际项目中的应用:

javascript 复制代码
// 在标签页组件中,确保滚动不会超出左边界
const leftPosition = Math.max(0, scrollX - 200);

// 计算元素是否在可视区域内
function isElementInViewport(element) {
  const rect = element.getBoundingClientRect();
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= window.innerHeight &&
    rect.right <= window.innerWidth
  );
}

其他常见场景

1. 百分比计算
javascript 复制代码
// 计算上传进度百分比
function calculateProgress(bytesUploaded, bytesTotal) {
  if (!bytesTotal || bytesTotal === 0) return 0;
  return Math.round((bytesUploaded / bytesTotal) * 100);
}

console.log(calculateProgress(50, 100)); // 50
console.log(calculateProgress(1, 3)); // 33
2. 限制数值范围
javascript 复制代码
/**
 * 将数值限制在指定范围内
 * @param {number} value - 要限制的数值
 * @param {number} min - 最小值
 * @param {number} max - 最大值
 * @returns {number} 限制后的数值
 */
function clamp(value, min, max) {
  return Math.max(min, Math.min(value, max));
}

// 使用示例
clamp(150, 0, 100); // 100
clamp(-50, 0, 100); // 0
clamp(50, 0, 100); // 50
clamp(0.75, 0, 1); // 0.75
3. 相对时间显示
javascript 复制代码
/**
 * 将时间差转换为相对时间描述
 * @param {number} diffSeconds - 时间差(秒)
 * @returns {string} 相对时间描述
 */
function getRelativeTime(diffSeconds) {
  const diff = Math.abs(diffSeconds);

  if (diff < 60) {
    return `${Math.ceil(diff)}分钟前`;
  } else if (diff < 3600) {
    return `${Math.ceil(diff / 60)}小时前`;
  } else if (diff < 86400) {
    return `${Math.ceil(diff / 3600)}天前`;
  } else {
    return `${Math.ceil(diff / 86400)}天前`;
  }
}

// 使用示例
console.log(getRelativeTime(30)); // "1分钟前"
console.log(getRelativeTime(1800)); // "30小时前"
console.log(getRelativeTime(7200)); // "2天前"

注意事项

1. 精度问题

JavaScript 使用 IEEE 754 双精度浮点数,某些计算可能出现精度误差:

javascript 复制代码
0.1 + 0.2 === 0.3; // false(实际上是 0.30000000000000004)

// 解决方案:使用 toFixed() 或比较差值
Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON; // true
(0.1 + 0.2).toFixed(1) === "0.3"; // true

2. NaN 和 Infinity

javascript 复制代码
Math.sqrt(-1); // NaN
Math.log(0); // -Infinity
1 / 0; // Infinity
parseInt("abc"); // NaN

// 检查是否为有效数字
Number.isNaN(NaN); // true
Number.isFinite(Infinity); // false
Number.isFinite(100); // true

3. 性能考虑

对于频繁调用的数学运算,可以考虑缓存结果或使用位运算优化:

javascript 复制代码
// 向下取整的替代方案(仅适用于正数)
Math.floor(4.9); // 4
4.9 | 0; // 4(位运算更快)

// 但要注意:位运算会将数字转换为 32 位整数
Math.floor(4294967296.9); // 4294967296
4294967296.9 | 0; // 0(溢出)

4. Math 方法不是构造函数

javascript 复制代码
// ❌ 错误
const m = new Math();
m.random();

// ✅ 正确
Math.random();

总结

Math 对象是前端开发中处理数值计算的得力助手。掌握以下核心要点:

📌 核心方法速查表

方法 用途 示例
Math.ceil() 向上取整 Math.ceil(4.1)5
Math.floor() 向下取整 Math.floor(4.9)4
Math.round() 四舍五入 Math.round(4.5)5
Math.max() 最大值 Math.max(1, 5, 3)5
Math.min() 最小值 Math.min(1, 5, 3)1
Math.random() 随机数 Math.random()0-1
Math.abs() 绝对值 Math.abs(-5)5
Math.pow() 幂运算 Math.pow(2, 3)8
Math.sqrt() 平方根 Math.sqrt(9)3

💡 最佳实践

  1. 文件分片 :用 Math.ceil() 计算分片数,用 Math.min() 限制边界
  2. 时间转换 :用 Math.floor() 提取整数部分,用 % 取余数
  3. 数值限制 :组合使用 Math.max()Math.min() 实现 clamp 功能
  4. 随机数生成Math.floor(Math.random() * (max - min + 1)) + min
  5. 注意精度 :浮点数运算时使用 Number.EPSILON 进行比较

🚀 进阶建议

  • 熟悉 ES6+ 的新特性,如指数运算符 **
  • 了解 Number 对象的静态方法(Number.isInteger()Number.isSafeInteger() 等)
  • 对于高精度计算,考虑使用专门的库(如 decimal.js、big.js)
  • 在性能敏感的场景中,合理使用位运算优化

相关推荐
Piko61411 小时前
H3C IRF2 堆叠实战:打造高可靠核心交换网络
运维·网络·笔记
茯苓gao13 小时前
嵌入式开发笔记:CANopen相关移位运算与通信协议术语详解
网络·嵌入式硬件·学习·信息与通信
万联WANFLOW14 小时前
SD-WAN 控制平面高可用怎么做?SDWAN 控制器挂了,全网会发生什么
运维·网络·分布式·架构
酱学编程14 小时前
【从零到一实现一个 AI Agent 框架 · 第四篇】04. 任务规划:拆解复杂目标 -
服务器·网络·数据库·人工智能
风行南方16 小时前
密码学之分组密码
网络·密码学
艾莉丝努力练剑16 小时前
OpenCode AI 编程:Ubuntu 24.04 环境安装与使用指南
linux·服务器·网络·人工智能·tcp/ip·ubuntu
谷雪_65817 小时前
Linux 网络命名空间:从内核原理到企业级容器网络架构全景实战
linux·网络·架构
liulilittle17 小时前
KCC 拥塞控制算法缺陷修复记录(26/07/05)
网络·tcp/ip·计算机网络·c·信息与通信·tcp·通信
Tian_Hang18 小时前
Eclipse Ditto 的权限策略
java·服务器·前端·网络·ide·ubuntu·eclipse