首页
/ JavaScript 原始数据类型与基础操作实战指南

JavaScript 原始数据类型与基础操作实战指南

2025-07-08 07:46:12作者:舒璇辛Bertina

前言

JavaScript 作为一门动态类型语言,其原始数据类型和基础操作是每位开发者必须掌握的核心知识。本文将通过一系列代码示例,深入讲解 JavaScript 中各种原始数据类型的特性和操作方法,帮助开发者夯实基础,避免常见陷阱。

1. typeof 操作符的全面解析

typeof 操作符是 JavaScript 中最基础的类型检测工具,它返回一个表示操作数类型的字符串。

typeof 50; // "number"
typeof "text"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof function () {}; // "function"
typeof 10n; // "bigint"
typeof Symbol(); // "symbol"
typeof [1, 2]; // "object"
typeof {}; // "object"

特殊案例解析

typeof NaN; // "number" (NaN 虽然表示"非数字",但类型仍是 number)
typeof undeclaredVar; // "undefined" (未声明变量)
typeof Infinity; // "number" (无限大也是数字类型)
typeof null; // "object" (历史遗留问题)
typeof /regex/; // "object" (正则表达式)

技术要点

  • 数组和函数本质上是对象的子类型
  • null 的类型判断是 JavaScript 的著名设计缺陷

2. 数字与字符串的隐式转换陷阱

JavaScript 中数字和字符串的拼接操作常常导致意外的隐式类型转换。

1 + "2"; // "12" (数字转为字符串)
1 + 2 + "3"; // "33" (先数字相加,再转为字符串)
"1" + 2; // "12" (数字转为字符串)
"1" + "2" + 3; // "123" (字符串拼接)
"1" + "2" + (3 + 4); // "127" (括号优先计算)

最佳实践

  • 明确使用类型转换函数而非依赖隐式转换
  • 复杂表达式使用括号明确运算顺序

3. 显式类型转换的正确姿势

数字转字符串

const num = 12;
String(num); // 推荐方式
num.toString(); // 方法调用
num + ""; // 隐式转换(不推荐)

字符串转数字

const str = "12";
Number(str); // 推荐方式
+str; // 一元运算符
parseInt(str); // 解析整数
parseFloat("12.34"); // 解析浮点数

注意事项

  • parseInt 总是指定基数参数避免八进制解析问题
  • 大数使用 BigInt 而非 parseInt

4. 大整数处理:BigInt 详解

JavaScript 的 Number 类型有精度限制,BigInt 用于处理大整数。

const bigNum1 = 1526688934595n;
const bigNum2 = 256489246848n;
const num3 = 1562365;

const bigSum = bigNum1 + bigNum2;
const total = bigNum1 + BigInt(num3); // 必须显式转换

限制

  • 不能与普通数字混合运算
  • 不能用于 Math 对象的方法
  • JSON 序列化需要自定义处理

5. 逻辑运算符的深度解析

逻辑 OR (||)

false || "default"; // "default" (短路求值)
0 || 42; // 42 (0 被视为 falsy)

逻辑 AND (&&)

true && "value"; // "value" (全部为真时返回最后一个)
null && "text"; // null (短路求值)

Nullish 合并运算符 (??)

null ?? "default"; // "default" (仅对 null/undefined 有效)
0 ?? 42; // 0 (不同于 ||)

双非运算符 (!!)

!!"text"; // true (显式转换为布尔值)
!!0; // false

6. Number 对象的实用方法

Number.isInteger(1.5); // false
Number.parseInt("5.8"); // 5
Number.parseFloat("-12.69x"); // -12.69
Number.isNaN("text" - 10); // true

(56.369).toFixed(2); // "56.37"
(32.458).toPrecision(3); // "32.5"

关键点

  • toFixedtoPrecision 都返回字符串
  • isNaN 与全局 isNaN 的区别在于类型检查

7. Math 对象的数学运算

Math.abs(-5); // 5
Math.floor(1.6); // 1
Math.ceil(2.4); // 3
Math.round(3.5); // 4
Math.max(-4, 5, 6); // 6
Math.sqrt(64); // 8
Math.trunc(-6.3); // -6

实用技巧

  • 使用 Math.random() 生成随机数时注意范围控制
  • Math.trunc()parseInt 更适合取整

8. 浮点数精度问题解决方案

JavaScript 使用 IEEE 754 双精度浮点数,导致著名的 0.1 + 0.2 ≠ 0.3 问题。

0.1 + 0.2 === 0.3; // false
Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON; // true

解决方案

  • 金融计算使用专门库如 decimal.js
  • 比较时使用误差范围而非严格相等
  • 展示时限制小数位数

9. 字符串操作大全

遍历字符串

// 传统 for 循环
for (let i = 0; i < str.length; i++) {
  console.log(str.charAt(i));
}

// ES6 方式
for (const char of str) {
  console.log(char);
}

// 函数式
[...str].forEach(char => console.log(char));

模板字符串高级用法

// 表达式插值
const total = `Sum: ${num1 + num2}`;

// 标签模板
function highlight(strings, ...values) {
  return strings.reduce((result, str, i) => 
    `${result}${str}<mark>${values[i] || ''}</mark>`, '');
}

highlight`Price: ${price} Discount: ${discount}`;

10. 错误处理最佳实践

try {
  // 可能出错的代码
  JSON.parse(invalidJson);
} catch (err) {
  // 处理特定错误类型
  if (err instanceof SyntaxError) {
    console.error("JSON 解析错误:", err.message);
  } else {
    throw err; // 重新抛出未知错误
  }
} finally {
  // 清理资源
  console.log("执行完成");
}

注意事项

  • 不要静默吞没错误
  • finally 块中避免 return 语句
  • 异步错误需要用 Promise.catch 处理

11. Symbol 的独特应用

Symbol 创建唯一标识符,常用于:

// 创建唯一属性键
const USER_KEY = Symbol('user');
obj[USER_KEY] = userData;

// 注册全局 Symbol
const GLOBAL_SYMBOL = Symbol.for('app.unique');

// 内置 Symbol 改变语言行为
class MyIterable {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
  }
}

12. 类型检查进阶技巧

// 区分数组和对象
Array.isArray([]); // true

// instanceof 检查原型链
new Date() instanceof Date; // true

// 构造函数检查
"".constructor === String; // true

// 鸭子类型检查
typeof obj.then === 'function'; // 可能是 Promise

13. WeakMap 的特殊应用场景

WeakMap 的键是弱引用,适合存储私有数据或元数据。

const privateData = new WeakMap();

class Person {
  constructor(name) {
    privateData.set(this, { name });
  }
  
  getName() {
    return privateData.get(this).name;
  }
}

const person = new Person("Alice");
console.log(person.getName()); // "Alice"

特点

  • 键必须是对象
  • 不可枚举
  • 不会阻止垃圾回收

结语

掌握 JavaScript 原始数据类型和基础操作是成为资深开发者的必经之路。本文涵盖了从类型检测、转换到各种特殊数据结构的全面知识,建议读者通过实际编码练习加深理解。记住,扎实的基础是构建复杂应用的基石。