关于Web APIs总结第三篇(完)

五.Bom操作

1.Window对象

1.1BOM(浏览器对象模型)
window
navigater
loaction
document
history
screen

window对象是一个全局对象,也可以说是JavaScript中的顶级对象

像document、alert()、console.log()这些都是window的属性,基本BOM的属性和方法都是window的。

所有通过var定义在全局作用域中的变量、函数都会变成window对象的属性和方法

window对象下的属性和方法调用的时候可以省略window

1.2定时器-延时函数

JavaScript 内置的一个用来让代码延迟执行的函数,叫 setTimeout

语法:

setTimeout(回调函数,等待的毫秒数)

setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略window

清除延时函数:

let timer = setTimeout(回调函数,等待的毫秒数)

clearTimeout(timer)

注意点

  1. 延时器需要等待,所以后面的代码先执行
  2. 每一次调用延时器都会产生一个新的延时器
1.3JS执行机制

JavaScript 的执行机制是其核心特性之一,涉及单线程事件循环(Event Loop)调用栈任务队列等概念。以下是详细解析:

1.3.1 单线程与异步

JavaScript 是单线程语言,但通过异步非阻塞机制处理并发操作(如网络请求、定时器等)。
关键点

  • 单线程:同一时间只能执行一个任务,避免多线程的复杂性(如死锁)。
  • 异步任务:通过回调函数、Promise、async/await 实现非阻塞操作。
1.3.2执行上下文(Execution Context)

代码执行时的环境,分为:

  • 全局执行上下文:代码首次执行时创建。
  • 函数执行上下文:每次调用函数时创建。
  • Eval 执行上下文(较少用)。

每个上下文包含:

  • 变量对象(VO):存储变量、函数声明。
  • 作用域链(Scope Chain):用于变量查找。
  • this 绑定:指向当前执行环境。
1.3.3. 调用栈(Call Stack)
  • **后进先出(LIFO)**结构,记录函数的调用顺序。
  • 函数执行时入栈,执行完毕出栈。
  • 栈溢出:递归过深时抛出 RangeError

示例

function foo() {
    console.log("foo");
    bar();
}
function bar() {
    console.log("bar");
}
foo(); // 调用栈顺序: foo → bar

1.3.4. 事件循环(Event Loop)

协调调用栈和任务队列的机制,分为以下步骤:

(1) 任务分类

  • 同步任务:立即执行,进入调用栈。

  • 异步任务

    :分为两类:

    • 宏任务(Macro Task)setTimeoutsetInterval、DOM 事件、I/O 操作。
    • 微任务(Micro Task)Promise.thenMutationObserverqueueMicrotask

(2) 执行流程

  1. 执行全局同步代码(调用栈)。
  2. 遇到异步任务:
    • 宏任务 → 交给 Web API 处理,完成后回调放入宏任务队列
    • 微任务 → 回调放入微任务队列
  3. 调用栈为空时:
    • 优先清空微任务队列(全部执行)。
    • 取出宏任务队列的第一个任务执行。
  4. 重复步骤 3(事件循环)。

示例

console.log("1"); // 同步

setTimeout(() => console.log("2"), 0); // 宏任务

Promise.resolve().then(() => console.log("3")); // 微任务

console.log("4"); // 同步

// 输出顺序: 1 → 4 → 3 → 2

1.3.5任务队列(Task Queues)
  • 宏任务队列:每次事件循环处理一个宏任务。
  • 微任务队列:必须在当前宏任务结束后立即清空(优先级更高)。

执行顺序
同步代码 → 微任务 → 宏任务 → (下一轮循环)

1.3.6. 关键概念对比
特性 宏任务 微任务
示例 setTimeoutsetInterval Promise.thenqueueMicrotask
队列优先级 高(当前循环末尾执行)
触发时机 下一次事件循环 当前任务结束后立即执行
1.3.7. 常见面试题分析

题目 1

setTimeout(() => console.log("A"), 0);
Promise.resolve().then(() => console.log("B"));
console.log("C");

答案C → B → A
解析:同步代码 C 最先执行;微任务 B 优先于宏任务 A

题目 2

console.log("Start");
setTimeout(() => console.log("Timeout"), 0);
Promise.resolve().then(() => {
    console.log("Promise");
    setTimeout(() => console.log("Inner Timeout"), 0);
});
console.log("End");

答案Start → End → Promise → Timeout → Inner Timeout
解析

  1. 同步代码 StartEnd
  2. 微任务 Promise 执行,其内部的 setTimeout 作为新宏任务加入队列。
  3. 执行初始宏任务 Timeout,最后执行 Inner Timeout
1.3.8. 总结
  • 调用栈处理同步任务,任务队列管理异步任务。
  • 微任务优先级高于宏任务
  • 事件循环是 JS 实现非阻塞的核心机制。

理解这些机制能有效避免异步编程中的常见问题(如执行顺序错误)。

1.4location对象

location 对象是浏览器提供的 JavaScript 内置对象,它包含了当前文档的 URL 信息,并提供了操作浏览器地址的方法。

1.4.1. location 对象属性

location 对象包含以下属性,这些属性都是可读写的(修改它们会导致浏览器导航到新的 URL):

属性 描述 示例
href 完整的 URL "https://example.com:8080/path/?query=string#hash"
protocol 协议部分(包括冒号) "https:"
host 主机名和端口号 "example.com:8080"
hostname 主机名 "example.com"
port 端口号 "8080"
pathname URL 路径部分 "/path/"
search 查询字符串(包括问号) "?query=string"
hash 锚部分(包括井号) "#hash"
origin 只读属性,返回协议+主机名+端口 "https://example.com:8080"
1.4.2. location 对象方法
方法 描述 示例
assign(url) 加载新文档 location.assign("https://new.com")
replace(url) 替换当前文档(不保留历史记录) location.replace("https://new.com")
reload() 重新加载当前页面 location.reload()
reload(forceGet) 强制从服务器重新加载 location.reload(true)
toString() 返回完整的 URL 字符串 location.toString()
1.4.3. 使用示例

获取当前 URL 信息

console.log("完整URL:", location.href);
console.log("协议:", location.protocol);
console.log("主机:", location.host);
console.log("路径:", location.pathname);
console.log("查询参数:", location.search);
console.log("锚点:", location.hash);

修改 URL

// 导航到新页面(会添加到历史记录)
location.href = "https://new.com";

// 替换当前页面(不会添加到历史记录)
location.replace("https://new.com");

// 修改查询字符串
location.search = "?page=2";

// 修改锚点(不会重新加载页面)
location.hash = "#section2";

解析查询参数

function getQueryParams() {
  const params = {};
  const queryString = location.search.substring(1);
  const pairs = queryString.split("&");
  
  pairs.forEach(pair => {
    const [key, value] = pair.split("=");
    params[decodeURIComponent(key)] = decodeURIComponent(value || "");
  });
  
  return params;
}

console.log(getQueryParams());

页面重定向

// 3秒后重定向
setTimeout(() => {
  location.href = "https://new.com";
}, 3000);

// 条件重定向
if (!userLoggedIn) {
  location.replace("/login");
}

1.4.4. 注意事项
  1. 修改 location 属性(除 hash 外)会导致页面重新加载
  2. replace() 方法不会在浏览器历史记录中创建新条目
  3. reload(true) 会绕过缓存,从服务器强制重新加载
  4. 现代前端框架(如 React、Vue)通常使用客户端路由,直接操作 location 可能会干扰框架的路由系统
1.4.5. 与 window.location 的关系

location 对象是 window 对象的属性,因此以下两种写法是等价的:

window.location.href;
location.href;

在大多数情况下,可以省略 window. 前缀直接使用 location

1.5navigator对象

navigator 对象是浏览器提供的 JavaScript 内置对象,它包含了有关浏览器的信息,包括浏览器名称、版本、平台、用户代理字符串等。

1.5.1. navigator 对象常用属性
属性 描述 示例值
appName 浏览器名称 "Netscape" (大多数现代浏览器返回此值)
appVersion 浏览器版本信息 "5.0 (Windows NT 10.0; Win64; x64)"
userAgent 用户代理字符串 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
platform 操作系统平台 "Win32"
language 浏览器主语言 "zh-CN"
languages 浏览器支持的语言数组 ["zh-CN", "zh", "en-US", "en"]
cookieEnabled 是否启用cookie true
onLine 是否联网 true
hardwareConcurrency CPU核心数 8
deviceMemory 设备内存(GB) 8
maxTouchPoints 最大触摸点数 5
1.5.2. navigator 对象常用方法
方法 描述 示例
javaEnabled() 是否启用Java navigator.javaEnabled()
sendBeacon() 异步发送少量数据 navigator.sendBeacon(url, data)
vibrate() 触发设备震动(移动设备) navigator.vibrate(200)
getBattery() 获取电池状态(Promise) navigator.getBattery().then(...)
getUserMedia() 获取媒体设备访问权限 navigator.mediaDevices.getUserMedia(...)
share() Web分享API navigator.share({title: '分享标题', url: 'https://example.com'})
1.5.3. 使用示例

检测浏览器基本信息

console.log('浏览器名称:', navigator.appName);
console.log('浏览器版本:', navigator.appVersion);
console.log('用户代理:', navigator.userAgent);
console.log('操作系统:', navigator.platform);
console.log('是否在线:', navigator.onLine);
console.log('是否启用cookie:', navigator.cookieEnabled);

检测浏览器类型

function detectBrowser() {
  const ua = navigator.userAgent;
  
  if (ua.indexOf('Chrome') > -1) return 'Chrome';
  if (ua.indexOf('Firefox') > -1) return 'Firefox';
  if (ua.indexOf('Safari') > -1) return 'Safari';
  if (ua.indexOf('Opera') > -1) return 'Opera';
  if (ua.indexOf('Edge') > -1) return 'Edge';
  if (ua.indexOf('MSIE') > -1 || ua.indexOf('Trident/') > -1) return 'IE';
  
  return 'Unknown';
}

console.log('当前浏览器:', detectBrowser());

使用sendBeacon发送数据

// 在页面卸载时可靠地发送数据
window.addEventListener('unload', function() {
  const data = JSON.stringify({event: 'page_exit', time: Date.now()});
  navigator.sendBeacon('/analytics', data);
});

检测设备特性

console.log('CPU核心数:', navigator.hardwareConcurrency);
console.log('设备内存(GB):', navigator.deviceMemory);

// 检测是否移动设备
const isMobile = /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
console.log('是否移动设备:', isMobile);

使用Web Share API

if (navigator.share) {
  document.getElementById('share-btn').addEventListener('click', async () => {
    try {
      await navigator.share({
        title: 'Web分享示例',
        text: '看看这个有趣的网站',
        url: 'https://example.com'
      });
      console.log('分享成功');
    } catch (err) {
      console.log('分享取消:', err);
    }
  });
} else {
  console.log('Web Share API不支持');
}

1.5.4. 注意事项
  1. 用户代理字符串不可靠userAgent可以被修改,不应仅依赖它来做关键功能检测
  2. 隐私考虑:某些属性如deviceMemory可能涉及隐私,浏览器可能限制访问
  3. 兼容性问题:新API如share()getBattery()等不是所有浏览器都支持
  4. 特性检测:推荐使用特性检测而非浏览器嗅探
1.5.5. 现代API扩展

现代navigator对象还包含许多新API:

  • 媒体设备navigator.mediaDevices (摄像头/麦克风访问)
  • 地理位置navigator.geolocation
  • 剪贴板navigator.clipboard
  • 蓝牙navigator.bluetooth
  • USBnavigator.usb
  • 网络信息navigator.connection

这些API通常需要用户授权才能使用。

1.6histroy对象

history 对象是浏览器提供的 JavaScript 内置对象,它允许开发者操作浏览器的会话历史记录(即当前标签页访问过的 URL 历史)。

1.6.1. history 对象属性
属性 描述 示例
length 返回历史记录列表中的 URL 数量(只读) history.length
scrollRestoration 控制页面刷新后是否恢复滚动位置(auto/manual history.scrollRestoration = 'manual'
state 返回当前历史记录条目的状态对象(只读) history.state
1.6.2. history 对象方法
  1. 核心导航方法
方法 描述 示例
back() 后退到上一个页面(等同于浏览器后退按钮) history.back()
forward() 前进到下一个页面(等同于浏览器前进按钮) history.forward()
go(n) 在历史记录中前进或后退 n 个页面 history.go(-2) (后退2页)
  1. 现代 HTML5 History API
方法 描述 示例
pushState(state, title, url) 添加新的历史记录条目(不刷新页面) history.pushState({page: 1}, "Page 1", "?page=1")
replaceState(state, title, url) 替换当前历史记录条目(不刷新页面) history.replaceState({page: 2}, "Page 2", "?page=2")
1.6.3. 使用示例
  1. 基本导航控制
// 后退一页
document.getElementById('back-btn').addEventListener('click', () => {
  history.back();
});

// 前进一页
document.getElementById('forward-btn').addEventListener('click', () => {
  history.forward();
});

// 前进或后退多页
document.getElementById('go-btn').addEventListener('click', () => {
  history.go(-2); // 后退2页
});

  1. 使用 History API 实现 SPA 路由
// 添加新历史记录
function navigateTo(page) {
  const state = { page };
  const title = `Page ${page}`;
  const url = `?page=${page}`;
  
  history.pushState(state, title, url);
  updateContent(page);
}

// 替换当前历史记录
function replaceCurrentPage(page) {
  const state = { page };
  const title = `Page ${page}`;
  const url = `?page=${page}`;
  
  history.replaceState(state, title, url);
  updateContent(page);
}

// 处理浏览器前进/后退
window.addEventListener('popstate', (event) => {
  const page = event.state?.page || 1;
  updateContent(page);
});

function updateContent(page) {
  document.getElementById('content').textContent = `当前页面: ${page}`;
}

  1. 状态管理示例
// 保存状态到历史记录
history.pushState({ 
  formData: {
    username: 'user123',
    progress: 75
  }
}, "Form Page", "/form");

// 恢复状态
window.addEventListener('popstate', (event) => {
  const savedState = event.state;
  if (savedState && savedState.formData) {
    console.log('恢复的表单数据:', savedState.formData);
    // 填充表单...
  }
});
  1. 禁止滚动恢复
// 禁用页面刷新后的自动滚动恢复
if (history.scrollRestoration) {
  history.scrollRestoration = 'manual';
}

1.6.4. 注意事项
  1. 安全限制
    • 只能操作同源的历史记录
    • 不能直接查看历史记录中的具体URL(隐私保护)
  2. URL 参数
    • pushStatereplaceState 的 URL 参数必须同源
    • 修改 URL 不会触发页面加载,但会改变地址栏显示
  3. SEO 考虑
    • 使用 History API 的单页应用需要配置服务器端渲染
  4. 兼容性
    • HTML5 History API 在现代浏览器中完全支持
    • IE 10+ 支持,但旧版 IE 支持有限
  5. 最佳实践
    • 总是与 popstate 事件一起使用
    • 确保状态对象是可序列化的(不包含函数、循环引用等)
    • 状态对象大小不宜过大(某些浏览器限制为 640k 字符)
1.6.5 与 window.history 的关系

history 对象是 window 对象的属性,以下两种写法等价:

window.history.back();
history.back();

在大多数情况下,可以省略 window. 前缀直接使用 history

2.本地存储

2.1本地存储分类
2.1.1Cookie
  • 特点:

    • 存储大小约4KB

    • 会随HTTP请求自动发送到服务器

    • 可设置过期时间

  • 使用场景:用户身份验证、会话管理

// 设置Cookie
document.cookie = "username=John; expires=Thu, 18 Dec 2025 12:00:00 UTC; path=/";

// 读取Cookie
const cookies = document.cookie.split(';');

2.1.2Web Storage

(1) localStorage

  • 特点:
    • 持久化存储(除非手动清除)
    • 存储大小5-10MB(各浏览器不同)
    • 同源策略限制

(2) sessionStorage

  • 特点:
    • 会话级存储(标签页关闭即清除)
    • 存储大小5-10MB
    • 同源策略限制
// localStorage使用
localStorage.setItem('theme', 'dark');
const theme = localStorage.getItem('theme');

// sessionStorage使用
sessionStorage.setItem('tempData', JSON.stringify({id: 1}));
const data = JSON.parse(sessionStorage.getItem('tempData'));

2.1.3IndexedDB
  • 特点:
    • 客户端数据库,存储大量结构化数据
    • 支持事务、索引查询
    • 异步API
  • 使用场景:离线应用、大数据量存储
// 打开/创建数据库
const request = indexedDB.open('myDatabase', 1);

request.onsuccess = (event) => {
  const db = event.target.result;
  // 数据库操作...
};

2.1.4Cache API
  • 特点:
    • 用于缓存网络请求响应
    • Service Worker配合使用
  • 使用场景:PWA应用、离线资源缓存
caches.open('my-cache').then(cache => {
  cache.add('/api/data');
});

2.2存储复杂数据类型
2.2.1JSON序列化方法

适用于Web Storage存储对象/数组

const user = {
  name: "张三",
  preferences: {
    theme: "dark",
    fontSize: 16
  }
};

// 存储
localStorage.setItem('user', JSON.stringify(user));

// 读取
const storedUser = JSON.parse(localStorage.getItem('user'));

2.2.2IndexedDB存储复杂对象

直接支持存储JavaScript对象

const transaction = db.transaction('users', 'readwrite');
const store = transaction.objectStore('users');

store.put({
  id: 1,
  name: "李四",
  tags: ["vip", "admin"],
  meta: {
    lastLogin: new Date()
  }
});

2.2.3特殊数据类型处理

(1) Date对象

// 存储
localStorage.setItem('lastUpdated', new Date().toISOString());

// 读取
const date = new Date(localStorage.getItem('lastUpdated'));

(2) Map/Set

const map = new Map([['key1', 'value1'], ['key2', 'value2']]);

// 存储
localStorage.setItem('myMap', JSON.stringify(Array.from(map.entries())));

// 读取
const mapData = new Map(JSON.parse(localStorage.getItem('myMap')));

2.3实践建议
  1. 数据安全

    • 敏感信息不要存储在客户端
    • 考虑使用加密库对数据进行加密
  2. 容量管理

    // 检查localStorage剩余空间
    function getLocalStorageRemainingSpace() {
      const testKey = 'test';
      let data = '';
      try {
        // 填充数据直到超出限制
        while(true) {
          data += 'xxxxxxxxxx';
          localStorage.setItem(testKey, data);
        }
      } catch (e) {
        localStorage.removeItem(testKey);
        return data.length;
      }
    }
    
    
  3. 错误处理

    try {
      localStorage.setItem('key', largeData);
    } catch (e) {
      if (e.name === 'QuotaExceededError') {
        console.error('存储空间不足');
        // 清理旧数据或提示用户
      }
    }
    
    
  4. 数据版本控制

    const storageVersion = 'v2.1';
    if(localStorage.getItem('version') !== storageVersion) {
      localStorage.clear();
      localStorage.setItem('version', storageVersion);
    }
    
    
  5. 性能优化

    • 大数据量优先使用IndexedDB
    • 频繁读写的数据可以先用内存缓存,再批量写入存储
2.4现代存储方案对比
方案 容量 持久性 数据结构 同步/异步 适用场景
Cookie 4KB 可设置 字符串 同步 小数据、身份验证
localStorage 5-10MB 持久 字符串 同步 用户偏好设置
sessionStorage 5-10MB 会话级 字符串 同步 临时数据
IndexedDB ≥250MB 持久 复杂类型 异步 离线应用、大数据
Cache API 动态 持久 请求/响应 异步 网络资源缓存

根据应用需求选择合适的存储方案,对于现代Web应用,通常需要组合使用多种存储技术。

六.正则&阶段案例

1.正则表达式介绍

正则表达式(Regular Expression,简称 regex)是用于匹配字符串中字符组合的模式,它是一种强大的字符串处理工具,主要用于:

  • 字符串搜索
  • 字符串替换
  • 数据验证
  • 字符串提取和分割

在 JavaScript 中,正则表达式通过 RegExp 对象实现,有两种创建方式:

// 字面量形式
const regex1 = /pattern/flags;

// 构造函数形式
const regex2 = new RegExp('pattern', 'flags');

2.正则表达式语法

2.1. 基础语法
语法 描述 示例
literal 直接匹配字符 /abc/ 匹配 “abc”
` ` 或操作
[] 字符集合 [abc] 匹配 “a”、“b” 或 “c”
[^] 否定字符集合 [^abc] 匹配非 “a”、“b”、“c” 的字符
() 分组 (abc)+ 匹配 “abc” 一次或多次
2.2.量词
量词 描述 示例
* 0次或多次 a* 匹配 “”, “a”, “aa”, …
+ 1次或多次 a+ 匹配 “a”, “aa”, …
? 0次或1次 a? 匹配 “”, “a”
{n} 恰好n次 a{2} 匹配 “aa”
{n,} 至少n次 a{2,} 匹配 “aa”, “aaa”, …
{n,m} n到m次 a{2,4} 匹配 “aa”, “aaa”, “aaaa”
2.3元字符(特殊字符)
元字符 描述 等价字符类
. 匹配除换行符外的任意字符 [^\n\r]
\d 数字字符 [0-9]
\D 非数字字符 [^0-9]
\w 单词字符(字母、数字、下划线) [A-Za-z0-9_]
\W 非单词字符 [^A-Za-z0-9_]
\s 空白字符(空格、制表符、换行等) [\t\n\v\f\r ]
\S 非空白字符 [^\t\n\v\f\r ]
\b 单词边界 -
\B 非单词边界 -
^ 字符串开始 -
$ 字符串结束 -
2.3修饰符(标志)
修饰符 描述 示例
i 不区分大小写 /abc/i 匹配 “ABC”
g 全局匹配(查找所有匹配) /a/g 在 “aaa” 中找到3个匹配
m 多行模式(^和$匹配每行的开始/结束) /^a/gm 在多行中匹配每行开头的a
s 允许.匹配换行符 /a.b/s 匹配 “a\nb”
u Unicode模式(正确处理4字节字符) /\u{1F600}/u 匹配
y 粘性匹配(从lastIndex开始精确匹配) /a/y 从指定位置匹配

3.五个实用案例

案例1:邮箱验证
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

console.log(emailRegex.test('[email protected]')); // true
console.log(emailRegex.test('invalid.email@'));    // false

案例2:提取URL中的域名
const url = 'https://www.example.com/path?query=string';
const domainRegex = /^(https?:\/\/)?([^\/\?]+)/i;
const match = url.match(domainRegex);

console.log(match[2]); // www.example.com

案例3:密码强度验证
// 至少8字符,包含大小写字母和数字
const passwordRegex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/;

console.log(passwordRegex.test('StrongPass1')); // true
console.log(passwordRegex.test('weak'));       // false

案例4:格式化电话号码
const phone = '1234567890';
const formatted = phone.replace(/^(\d{3})(\d{3})(\d{4})$/, '($1) $2-$3');

console.log(formatted); // (123) 456-7890

案例5:移除HTML标签
const html = '
Hello World
'; const cleanText = html.replace(/<[^>]*>/g, ''); console.log(cleanText); // Hello World

4.高级技巧

1. 非捕获组
// 使用 (?:...) 表示不捕获的分组
const dateRegex = /(\d{4})-(?:\d{2})-(\d{2})/;
const dateMatch = '2023-05-15'.match(dateRegex);

console.log(dateMatch); // ["2023-05-15", "2023", "15"]
2. 回溯引用
// 匹配重复单词
const repeatRegex = /\b(\w+)\s+\1\b/;

console.log(repeatRegex.test('hello hello')); // true
console.log(repeatRegex.test('hello world')); // false

3. 正向/负向预查
// 正向肯定预查 (?=...)
const hasNumberRegex = /^(?=.*\d).+$/;

// 正向否定预查 (?!...)
const noSpecialCharRegex = /^(?!.*[@#$%]).+$/;

5.常见问题解决

1. 贪婪匹配 vs 惰性匹配
const greedyRegex = /<.*>/;      // 匹配整个 
...
const lazyRegex = /<.*?>/; // 只匹配单个标签
2. 多行匹配
const multiLineText = `Line 1
Line 2
Line 3`;

// 不使用m修饰符
console.log(/^Line/g.test(multiLineText)); // false

// 使用m修饰符
console.log(/^Line/gm.test(multiLineText)); // true

3. Unicode字符匹配
// 不使用u修饰符
console.log(/^.$/.test('')); // false

// 使用u修饰符
console.log(/^.$/u.test('')); // true

正则表达式是JavaScript中非常强大的工具,掌握它可以极大提高字符串处理的效率和灵活性。建议从简单模式开始练习,逐步掌握更复杂的表达式。

你可能感兴趣的:(前端,javascript)