11JavaScript高级程序设计(第4版)

JavaScript标准库

内置功能

集合正则表达式日期国际化

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第11章:JavaScript标准库(Standard Library)

一、导读

1.1 本章学习目标

第11章介绍JavaScript的标准库。本章核心目标:

  • 掌握集合类型:Set、Map、WeakSet、WeakMap
  • 熟练使用正则表达式:创建、测试、匹配
  • 掌握日期处理:Date对象
  • 了解国际化API:Intl对象
  • 掌握JSON处理

1.2 为什么本章如此重要

JavaScript标准库提供了强大的内置功能。Set和Map提供了高效的数据结构,正则表达式是文本处理的利器,Date和Intl处理日期和国际化。掌握这些内置功能能大大提高开发效率。

1.3 核心问题引导

Set和Array有什么区别?什么时候用Set?

Map和普通对象有什么区别?

正则表达式的贪婪匹配和非贪婪匹配有什么区别?

WeakMap的"弱引用"是什么意思?


二、核心概念详解

11.1 Set和Map

javascript
// Set:不重复的值集合
let set = new Set([1, 2, 3, 2, 1]);
console.log(set.size);  // 3
set.add(4);
set.delete(1);
console.log(set.has(2));  // true

// 遍历
for (let item of set) {
  console.log(item);
}

// 数组去重
let arr = [1, 2, 2, 3, 3, 3];
let unique = [...new Set(arr)];
console.log(unique);  // [1, 2, 3]

// Map:键值对集合
let map = new Map();
map.set("name", "Alice");
map.set("age", 20);
console.log(map.get("name"));  // "Alice"
console.log(map.size);         // 2

// 遍历
for (let [key, value] of map) {
  console.log(`${key}: ${value}`);
}

// Map vs Object
// Map的键可以是任意类型
let objKey = {};
map.set(objKey, "value");
console.log(map.get(objKey));  // "value"

// WeakMap:弱引用
let wm = new WeakMap();
let obj = {};
wm.set(obj, "value");
// obj被垃圾回收后,wm中的条目也会被移除
// WeakMap不可遍历

11.2 正则表达式

javascript
// 创建正则
let regex1 = /hello/i;  // 字面量
let regex2 = new RegExp("hello", "i");  // 构造函数

// 测试
let str = "Hello, World!";
console.log(regex1.test(str));      // true
console.log(str.match(regex1));     // ["Hello"]

// 常用模式
let email = "test@example.com";
let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
console.log(emailRegex.test(email));  // true

// 替换
let text = "Hello 123 World 456";
let result = text.replace(/\d+/g, "NUM");
console.log(result);  // "Hello NUM World NUM"

// 分组和捕获
let dateStr = "2024-01-15";
let dateRegex = /(\d{4})-(\d{2})-(\d{2})/;
let match = dateStr.match(dateRegex);
console.log(match[1]);  // "2024"
console.log(match[2]);  // "01"
console.log(match[3]);  // "15"

// 命名捕获组
let namedRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let namedMatch = dateStr.match(namedRegex);
console.log(namedMatch.groups.year);   // "2024"
console.log(namedMatch.groups.month);  // "01"

// 常用方法
console.log("hello".search(/l/));     // 2
console.log("hello".split(/\s+/));    // ["hello"]

11.3 Date对象

javascript
// 创建日期
let now = new Date();
let specific = new Date("2024-01-15");
let fromParts = new Date(2024, 0, 15);  // 月份从0开始

// 获取组件
console.log(now.getFullYear());
console.log(now.getMonth() + 1);  // 0-11
console.log(now.getDate());
console.log(now.getDay());        // 星期几(0-6)
console.log(now.getHours());
console.log(now.getMinutes());
console.log(now.getTime());       // 时间戳

// 格式化
console.log(now.toISOString());
console.log(now.toLocaleDateString("zh-CN"));
console.log(now.toLocaleTimeString("zh-CN"));

// Intl.DateTimeFormat
let formatter = new Intl.DateTimeFormat("zh-CN", {
  year: "numeric",
  month: "long",
  day: "numeric",
  weekday: "long"
});
console.log(formatter.format(now));

// 日期计算
let tomorrow = new Date(now);
tomorrow.setDate(tomorrow.getDate() + 1);

// 时间差
let start = new Date("2024-01-01");
let end = new Date("2024-12-31");
let diff = end - start;
let days = Math.floor(diff / (1000 * 60 * 60 * 24));
console.log(days);

11.4 JSON

javascript
// 序列化
let obj = {name: "Bob", age: 25, hobbies: ["reading", "coding"]};
let jsonStr = JSON.stringify(obj);
console.log(jsonStr);

// 格式化输出
console.log(JSON.stringify(obj, null, 2));

// 自定义序列化
let custom = JSON.stringify(obj, (key, value) => {
  if (key === "age") return undefined;  // 过滤掉age
  return value;
});

// 解析
let parsed = JSON.parse(jsonStr);
console.log(parsed.name);

// 处理日期
let withDate = {name: "Alice", date: new Date()};
let serialized = JSON.stringify(withDate);
let deserialized = JSON.parse(serialized, (key, value) => {
  if (key === "date") return new Date(value);
  return value;
});

三、实战案例

3.1 文本分析工具

javascript
class TextAnalyzer {
  constructor(text) {
    this.text = text;
  }
  
  wordCount() {
    return this.text.split(/\s+/).filter(w => w.length > 0).length;
  }
  
  charCount() {
    return this.text.length;
  }
  
  mostCommonWords(n = 5) {
    const words = this.text.toLowerCase()
      .match(/\b\w+\b/g) || [];
    
    const freq = new Map();
    for (const word of words) {
      freq.set(word, (freq.get(word) || 0) + 1);
    }
    
    return [...freq.entries()]
      .sort((a, b) => b[1] - a[1])
      .slice(0, n);
  }
  
  extractEmails() {
    const regex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
    return this.text.match(regex) || [];
  }
  
  extractUrls() {
    const regex = /https?:\/\/[^\s]+/g;
    return this.text.match(regex) || [];
  }
}

const text = `
  Contact us at support@example.com or visit https://example.com.
  We also have info@example.com for more details.
`;

const analyzer = new TextAnalyzer(text);
console.log("Words:", analyzer.wordCount());
console.log("Top words:", analyzer.mostCommonWords(3));
console.log("Emails:", analyzer.extractEmails());
console.log("URLs:", analyzer.extractUrls());

四、本章小结

第11章介绍了JavaScript标准库:Set/Map集合、正则表达式、Date日期处理、JSON序列化、Intl国际化。这些内置功能提供了强大的数据处理能力。


五、思考与练习

思考题

Set的时间复杂度是多少?和Array相比有什么优势?

正则表达式的回溯是什么?如何避免性能问题?

Date对象有什么已知问题?Temporal API如何解决?

JSON不能序列化哪些JavaScript值?

编程练习

使用Set实现集合运算(并集、交集、差集)。

编写一个正则表达式验证密码强度。

实现一个日期范围选择器。


11/14Java
0%