JavaScript使用IEEE 754标准的64位双精度浮点数表示所有数字。
// 整数
let integer = 42;
let negative = -10;
// 浮点数
let float = 3.14;
let decimal = 0.5;
let scientific = 2.5e6; // 2500000(科学计数法)
// 数字可以是任意大小(在安全范围内)
let safeInteger = Number.MAX_SAFE_INTEGER; // 9007199254740991
let minInteger = Number.MIN_SAFE_INTEGER; // -9007199254740991
// 最大值和最小值
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
console.log(Number.MIN_VALUE); // 5e-324
// 安全整数范围
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
// 检查是否在安全范围内
console.log(Number.isSafeInteger(42)); // true
console.log(Number.isSafeInteger(9007199254740992)); // false
// 转换为字符串
let num = 42;
console.log(num.toString()); // "42"
console.log(num.toString(2)); // "101010"(二进制)
console.log(num.toString(16)); // "2a"(十六进制)
// 固定小数位数
let price = 3.14159;
console.log(price.toFixed(2)); // "3.14"
console.log(price.toFixed(4)); // "3.1416"
// 科学计数法
console.log(price.toExponential(2)); // "3.14e+0"
// 精度表示
console.log(price.toPrecision(4)); // "3.142"
// 二进制(0b或0B开头)
let binary = 0b1010; // 10
console.log(binary); // 10
// 八进制(0o或0O开头)
let octal = 0o755; // 493
console.log(octal); // 493
// 十六进制(0x或0X开头)
let hex = 0xFF; // 255
console.log(hex); // 255
// ES2021:数字分隔符
let million = 1_000_000;
let bytes = 0xFF_FF_FF_FF;
console.log(million); // 1000000
let big = 2.5e6; // 2500000
let small = 1.5e-3; // 0.0015
console.log(big); // 2500000
console.log(small); // 0.0015
NaN表示"不是一个数字",但它本身是数字类型:
console.log(typeof NaN); // "number"
// 产生NaN的情况
console.log(Number("abc")); // NaN
console.log(0 / 0); // NaN
console.log(Math.sqrt(-1)); // NaN
console.log(parseInt("东巴文")); // NaN
// NaN的特性
console.log(NaN === NaN); // false(NaN不等于任何值,包括自己)
// 检测NaN
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN("abc")); // false
console.log(isNaN("abc")); // true(先转换再判断)
// 正确的NaN检测
function isRealNaN(value) {
return typeof value === "number" && Number.isNaN(value);
}
// 正无穷和负无穷
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
// 最大值溢出
console.log(Number.MAX_VALUE * 2); // Infinity
// 检测无穷
console.log(Number.isFinite(42)); // true
console.log(Number.isFinite(Infinity)); // false
console.log(Number.isFinite(NaN)); // false
// 无穷运算
console.log(Infinity + 1); // Infinity
console.log(Infinity * 2); // Infinity
console.log(Infinity / Infinity); // NaN
console.log(Infinity - Infinity); // NaN
let positiveZero = 0;
let negativeZero = -0;
console.log(positiveZero === negativeZero); // true
// 区分正零和负零
console.log(Object.is(0, -0)); // false
console.log(1 / 0); // Infinity
console.log(1 / -0); // -Infinity
JavaScript使用IEEE 754双精度浮点数,存在精度问题:
// 经典的精度问题
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false
// 其他精度问题
console.log(0.07 * 100); // 7.000000000000001
console.log(0.1 + 0.7); // 0.7999999999999999
// 方案1:使用toFixed(返回字符串)
let result = (0.1 + 0.2).toFixed(1);
console.log(result); // "0.3"
console.log(parseFloat(result)); // 0.3
// 方案2:乘以倍数再除以倍数
function add(a, b) {
return (a * 100 + b * 100) / 100;
}
console.log(add(0.1, 0.2)); // 0.3
// 方案3:使用Number.EPSILON比较
function isEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
console.log(isEqual(0.1 + 0.2, 0.3)); // true
// 方案4:使用第三方库(如decimal.js)
// import Decimal from 'decimal.js';
// console.log(new Decimal(0.1).plus(0.2).toNumber()); // 0.3
东巴文提醒:涉及金额计算时,建议使用整数(分)或专门的库来避免精度问题。
Math对象提供了丰富的数学方法。
console.log(Math.PI); // 3.141592653589793
console.log(Math.E); // 2.718281828459045
console.log(Math.SQRT2); // 1.4142135623730951
console.log(Math.LN2); // 0.6931471805599453
console.log(Math.LN10); // 2.302585092994046
let num = 3.7;
// 向下取整
console.log(Math.floor(3.7)); // 3
console.log(Math.floor(-3.7)); // -4
// 向上取整
console.log(Math.ceil(3.2)); // 4
console.log(Math.ceil(-3.2)); // -3
// 四舍五入
console.log(Math.round(3.5)); // 4
console.log(Math.round(3.4)); // 3
console.log(Math.round(-3.5)); // -3
// 截断(去掉小数部分)
console.log(Math.trunc(3.7)); // 3
console.log(Math.trunc(-3.7)); // -3
// 0到1之间的随机数
console.log(Math.random());
// 0到9之间的随机整数
console.log(Math.floor(Math.random() * 10));
// 1到10之间的随机整数
console.log(Math.floor(Math.random() * 10) + 1);
// 任意范围的随机整数
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(getRandomInt(5, 15));
// 随机数组元素
const colors = ["红", "绿", "蓝", "黄"];
const randomColor = colors[Math.floor(Math.random() * colors.length)];
console.log(Math.max(1, 2, 3, 4, 5)); // 5
console.log(Math.min(1, 2, 3, 4, 5)); // 1
// 数组中的最大值和最小值
const numbers = [1, 5, 3, 9, 2];
console.log(Math.max(...numbers)); // 9
console.log(Math.min(...numbers)); // 1
// 幂运算
console.log(Math.pow(2, 10)); // 1024
console.log(2 ** 10); // 1024(ES6语法)
// 平方根
console.log(Math.sqrt(16)); // 4
// 立方根
console.log(Math.cbrt(27)); // 3
// n次方根
function nthRoot(num, n) {
return Math.pow(num, 1 / n);
}
console.log(nthRoot(16, 4)); // 2
// 注意:参数是弧度,不是角度
console.log(Math.sin(0)); // 0
console.log(Math.sin(Math.PI / 2)); // 1
console.log(Math.cos(0)); // 1
console.log(Math.tan(Math.PI / 4)); // 1
// 角度转弧度
function toRadians(degrees) {
return degrees * Math.PI / 180;
}
// 弧度转角度
function toDegrees(radians) {
return radians * 180 / Math.PI;
}
console.log(Math.sin(toRadians(90))); // 1
// 绝对值
console.log(Math.abs(-5)); // 5
// 符号
console.log(Math.sign(-5)); // -1
console.log(Math.sign(0)); // 0
console.log(Math.sign(5)); // 1
// 对数
console.log(Math.log(Math.E)); // 1
console.log(Math.log2(8)); // 3
console.log(Math.log10(100)); // 2
// 勾股定理
console.log(Math.hypot(3, 4)); // 5
字符串是由零个或多个字符组成的序列,用单引号、双引号或反引号包围。
// 单引号
let single = '东巴文';
// 双引号
let double = "东巴文";
// 反引号(模板字符串)
let template = `东巴文`;
// 构造函数
let constructed = new String("东巴文");
console.log(typeof single); // "string"
console.log(typeof constructed); // "object"
// 字符串是不可变的
let str = "东巴文";
str[0] = "西"; // 无效,不会改变原字符串
console.log(str); // "东巴文"
// 字符串长度
console.log("东巴文".length); // 3
// 访问字符
let text = "Hello";
console.log(text[0]); // "H"
console.log(text.charAt(0)); // "H"
console.log(text.charAt(10)); // ""(空字符串)
console.log(text[10]); // undefined
let escaped = "他说:\"你好\"";
console.log(escaped); // 他说:"你好"
// 常用转义字符
console.log("换行\n第二行");
console.log("制表符\t内容");
console.log("回车\r换行");
console.log("反斜杠\\");
console.log("单引号\'");
console.log("双引号\"");
| 转义字符 | 含义 | 东巴文说明 |
|---|---|---|
| \n | 换行 | New Line |
| \t | 制表符 | Tab |
| \r | 回车 | Carriage Return |
| \ | 反斜杠 | Backslash |
| ' | 单引号 | Single Quote |
| " | 双引号 | Double Quote |
| \uXXXX | Unicode字符 | 如 \u4e2d(中) |
let str = "东巴文学习JavaScript";
// indexOf - 查找子串位置
console.log(str.indexOf("学习")); // 3
console.log(str.indexOf("Python")); // -1(未找到)
// lastIndexOf - 从后往前查找
console.log(str.lastIndexOf("a")); // 10
// includes - 是否包含
console.log(str.includes("东巴文")); // true
console.log(str.includes("Python")); // false
// startsWith - 是否以某字符串开头
console.log(str.startsWith("东巴文")); // true
// endsWith - 是否以某字符串结尾
console.log(str.endsWith("Script")); // true
// search - 正则搜索
console.log(str.search(/Java/)); // 5
let str = "东巴文学习JavaScript";
// slice - 切片(推荐)
console.log(str.slice(0, 3)); // "东巴文"
console.log(str.slice(3)); // "学习JavaScript"
console.log(str.slice(-6)); // "Script"
console.log(str.slice(-10, -6)); // "学习J"
// substring - 子串
console.log(str.substring(0, 3)); // "东巴文"
console.log(str.substring(3, 0)); // "东巴文"(自动调整顺序)
// substr - 指定位置和长度(已废弃,不推荐)
console.log(str.substr(0, 3)); // "东巴文"
// charAt - 获取指定位置字符
console.log(str.charAt(0)); // "东"
// charCodeAt - 获取字符编码
console.log(str.charCodeAt(0)); // 19996("东"的Unicode编码)
let str = "Hello 东巴文";
console.log(str.toUpperCase()); // "HELLO 东巴文"
console.log(str.toLowerCase()); // "hello 东巴文"
// 首字母大写
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
console.log(capitalize("hello")); // "Hello"
let str = " 东巴文 ";
// trim - 去除两端空白
console.log(str.trim()); // "东巴文"
// trimStart / trimLeft - 去除开头空白
console.log(str.trimStart()); // "东巴文 "
// trimEnd / trimRight - 去除结尾空白
console.log(str.trimEnd()); // " 东巴文"
// repeat - 重复
console.log("东巴文".repeat(3)); // "东巴文东巴文东巴文"
// padStart - 开头填充
console.log("5".padStart(3, "0")); // "005"
// padEnd - 结尾填充
console.log("5".padEnd(3, "0")); // "500"
// replace - 替换(只替换第一个)
let text = "东巴文东巴文";
console.log(text.replace("东巴文", "DBW")); // "DBW东巴文"
// replaceAll - 替换所有(ES2021)
console.log(text.replaceAll("东巴文", "DBW")); // "DBWDBW"
// 使用正则替换所有
console.log(text.replace(/东巴文/g, "DBW")); // "DBWDBW"
// split - 分割成数组
let str = "东巴文,学习,JavaScript";
let arr = str.split(",");
console.log(arr); // ["东巴文", "学习", "JavaScript"]
// join - 数组连接成字符串
console.log(arr.join("-")); // "东巴文-学习-JavaScript"
// 分割每个字符
console.log("东巴文".split("")); // ["东", "巴", "文"]
模板字符串使用反引号,支持多行字符串和插值表达式。
// 普通字符串
let greeting = "你好," + name + "!";
// 模板字符串
let name = "东巴文";
let greeting = `你好,${name}!`;
console.log(greeting); // "你好,东巴文!"
// 表达式插值
let a = 10;
let b = 20;
console.log(`${a} + ${b} = ${a + b}`); // "10 + 20 = 30"
// 调用函数
function getPrice() {
return 99.99;
}
console.log(`价格:${getPrice()}元`); // "价格:99.99元"
// 普通字符串(需要使用\n)
let html1 = "<div>\n <p>东巴文</p>\n</div>";
// 模板字符串(直接换行)
let html2 = `<div>
<p>东巴文</p>
</div>`;
console.log(html1 === html2); // true
function highlight(strings, ...values) {
let result = strings[0];
for (let i = 0; i < values.length; i++) {
result += `<strong>${values[i]}</strong>${strings[i + 1]}`;
}
return result;
}
let name = "东巴文";
let age = 1;
let result = highlight`我叫${name},今年${age}岁。`;
console.log(result); // "我叫<strong>东巴文</strong>,今年<strong>1</strong>岁。"
布尔类型只有两个值:true和false。
let isActive = true;
let isLoggedIn = false;
console.log(typeof true); // "boolean"
console.log(typeof false); // "boolean"
// Boolean()函数
console.log(Boolean(1)); // true
console.log(Boolean(0)); // false
console.log(Boolean("东巴文")); // true
console.log(Boolean("")); // false
console.log(Boolean([])); // true
console.log(Boolean({})); // true
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
// 双重否定
console.log(!!1); // true
console.log(!!0); // false
console.log(!!""); // false
console.log(5 > 3); // true
console.log(5 < 3); // false
console.log(5 >= 5); // true
console.log(5 <= 4); // false
// 相等比较
console.log(5 == "5"); // true(隐式转换)
console.log(5 === "5"); // false(严格相等)
console.log(5 != "5"); // false
console.log(5 !== "5"); // true
// 逻辑与(&&)
console.log(true && true); // true
console.log(true && false); // false
console.log(false && true); // false(短路)
// 逻辑或(||)
console.log(true || false); // true
console.log(false || true); // true
console.log(true || true); // true(短路)
// 逻辑非(!)
console.log(!true); // false
console.log(!false); // true
console.log(!!true); // true
Undefined类型只有一个值:undefined。
// 未初始化的变量
let x;
console.log(x); // undefined
// 未提供的参数
function greet(name) {
console.log(name);
}
greet(); // undefined
// 不存在的属性
let obj = {};
console.log(obj.name); // undefined
// 函数没有返回值
function noReturn() {}
console.log(noReturn()); // undefined
let x;
// 使用严格相等
console.log(x === undefined); // true
// 使用typeof(安全,不会报错)
console.log(typeof x === "undefined"); // true
// 未声明的变量
// console.log(notDeclared); // ReferenceError
console.log(typeof notDeclared); // "undefined"
| 特性 | undefined | null | 东巴文说明 |
|---|---|---|---|
| 含义 | 未定义 | 空值 | undefined是"没有",null是"空" |
| 类型 | undefined | object | null的typeof是历史遗留问题 |
| 出现场景 | 自动产生 | 手动赋值 | undefined是默认值 |
| 使用建议 | 不主动赋值 | 主动赋空值 | null表示"无值" |
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object"
console.log(undefined == null); // true
console.log(undefined === null); // false
// 最佳实践
let name; // undefined(未赋值)
let user = null; // null(明确表示空值)
Null类型只有一个值:null,表示"空"或"无"。
// 表示空值
let user = null; // 暂时没有用户
// 条件判断
if (user === null) {
console.log("没有用户");
}
// 清除引用
let obj = { name: "东巴文" };
obj = null; // 解除引用,便于垃圾回收
// 函数参数默认值
function greet(name = null) {
if (name === null) {
return "你好,陌生人";
}
return `你好,${name}`;
}
let value = null;
// 使用严格相等
console.log(value === null); // true
// 同时检测null和undefined
console.log(value == null); // true
console.log(value == undefined); // true
// 只检测null
function isNull(value) {
return value === null;
}
Symbol是ES6引入的新原始类型,表示独一无二的值。
// 创建Symbol
let sym1 = Symbol();
let sym2 = Symbol("描述");
console.log(typeof sym1); // "symbol"
console.log(sym2.description); // "描述"
// 每个Symbol都是唯一的
let sym3 = Symbol("东巴文");
let sym4 = Symbol("东巴文");
console.log(sym3 === sym4); // false
let name = Symbol("name");
let age = Symbol("age");
let user = {
[name]: "东巴文",
[age]: 1,
email: "test@example.com"
};
console.log(user[name]); // "东巴文"
console.log(user[age]); // 1
// Symbol属性不会被常规方法遍历
console.log(Object.keys(user)); // ["email"]
console.log(Object.getOwnPropertySymbols(user)); // [Symbol(name), Symbol(age)]
// Symbol.for - 创建或获取全局Symbol
let sym1 = Symbol.for("app.id");
let sym2 = Symbol.for("app.id");
console.log(sym1 === sym2); // true
// Symbol.keyFor - 获取全局Symbol的key
console.log(Symbol.keyFor(sym1)); // "app.id"
// Symbol.iterator - 迭代器
let arr = [1, 2, 3];
let iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
// Symbol.toStringTag - 自定义toString标签
class User {
get [Symbol.toStringTag]() {
return "User";
}
}
console.log(Object.prototype.toString.call(new User())); // "[object User]"
BigInt是ES2020引入的类型,用于表示任意大的整数。
// 使用n后缀
let big1 = 9007199254740991n;
console.log(big1); // 9007199254740991n
// 使用BigInt()函数
let big2 = BigInt("9007199254740992");
console.log(big2); // 9007199254740992n
// 从数字转换
let big3 = BigInt(123);
console.log(big3); // 123n
let a = 10n;
let b = 5n;
console.log(a + b); // 15n
console.log(a - b); // 5n
console.log(a * b); // 50n
console.log(a / b); // 2n(整数除法,向下取整)
console.log(a % b); // 0n
console.log(a ** 2n); // 100n
// 不能与普通数字混合运算
// console.log(10n + 5); // TypeError
// 需要显式转换
console.log(10n + BigInt(5)); // 15n
console.log(Number(10n) + 5); // 15
| 特性 | Number | BigInt | 东巴文说明 |
|---|---|---|---|
| 精度 | 53位安全整数 | 任意精度 | BigInt无精度限制 |
| 小数 | 支持 | 不支持 | BigInt只能表示整数 |
| Math方法 | 支持 | 不支持 | Math.sqrt(4n)报错 |
| 混合运算 | - | 不允许 | 需要显式转换 |
| JSON序列化 | 支持 | 不支持 | 需要转换为字符串 |
// 大数计算
let result = 1n;
for (let i = 1n; i <= 100n; i++) {
result *= i;
}
console.log(result); // 100的阶乘
// JSON序列化
let big = 123n;
// JSON.stringify({ value: big }); // TypeError
// 解决方案
JSON.stringify({ value: big.toString() }); // '{"value":"123"}'
掌握了原始类型后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
🔢 东巴文寄语:原始类型是JavaScript的基础数据类型,理解它们的特性和方法,能让你写出更高效、更安全的代码。在 db-w.cn,我们帮你打好每一个基础!