说明:此文章用作个人学习记录,若有任何问题或建议欢迎大家在评论区讨论
文章目录
前言
在前面的学习中,我们已经深入了解了对象 (Object
)、数组 (Array
)、和函数 (function
)
这三种最常用的引用类型
本文作为 JavaScript 数据类型的最后一篇,
我们将详细探讨日期 (Date
)、正则表达式 (RegExp
)、错误对象 (Error
)
以及 ES6 引入的新类型:Map
、Set
、WeakMap
、WeakSet
我们将从它们的定义、实现到常见问题和解决方案,进行全方位的讲解
如果把 JavaScript 比作一个乐高玩具,
那么在完成了所有数据类型的学习后,你就相当于掌握了构建这个乐高玩具的所有零件
下一篇开始,我们将进入控制语句和循环语句的学习,尝试将这些乐高零件组合起来
开始写的时候,真没预计到单是数据类型,就写了1个基础篇+6个进阶篇
只能说是越深入研究,越能发现JavaScript的有趣之处吧
一、日期 (Date)
1. Date 类型的定义
Date
对象是 JavaScript 用来处理日期和时间的内置对象
记录从 1970 年 1 月 1 日 00:00:00 UTC 起到现在的时间点,称为 “Unix 时间戳”
这也是为什么几乎所有电子设备的初始时间都是1970.01.01
通过 Date
对象,我们可以获取当前时间、设定日期、比较日期、计算时间差
2. 创建 Date
- 当前时间
创建一个表示当前日期和时间的Date
对象
示例:const now = new Date(); console.log(now); // 输出当前的日期和时间
-
日期字符串创建
传入一个日期的字符串,Date
会自动解析并创建一个对应的日期对象
示例:const date = new Date('2024-10-21'); console.log(date);
日期字符串格式:
JavaScript能识别多种日期字符串的格式,
但是推荐只使用一种标准格式,即ISO 8601格式- 格式:YYYY-MM-DDTHH:mm:ss.sssZ
- YYYY:年(四位数)
- MM:月(01 到 12)
- DD:日(01 到 31)
- T:日期和时间的分隔符
- HH:mm:ss.sss:时间部分
示例:
const date = new Date('2024-10-21T15:30:00+08:00'); //北京时间是在+8时区,所以这里+08:00 console.log(date);
-
年、月、日创建
格式:new Date(year, month, day, hours, minutes, seconds, milliseconds)
,
未指定的部分会被设为 0const sDate = new Date(2024, 9, 21); // 月份从0开始,0代表1月 console.log(sDate);
-
时间戳创建
传入一个数字作为参数,表示从 1970 年 1 月 1 日开始的毫秒数。const timestampDate = new Date(0); console.log(timestampDate); // 输出: Thu Jan 01 1970 00:00:00 GMT+0000 (UTC)
该方式在日志记录、服务器间的远程交互以及精准时间差计算等场景中非常实用
3. 常用方法
-
获取日期和时间
const now = new Date(); console.log(now.getFullYear()); // 获取年份 console.log(now.getMonth()); // 获取月份(0-11,0表示1月) console.log(now.getDate()); // 获取日期(1-31) console.log(now.getDay()); // 获取星期几(0-6,0表示周日) console.log(now.getHours()); // 获取小时(0-23) console.log(now.getMinutes()); // 获取分钟(0-59) console.log(now.getSeconds()); // 获取秒数(0-59)
-
设置日期和时间
const myDate = new Date(); myDate.setFullYear(2025); // 设置年份为 2025 myDate.setMonth(5); // 设置月份为 6月 myDate.setDate(15); // 设置日期为 15日
4. 日期格式化
JavaScript 中的 Date
对象自带的方法对于日期格式化相对有限
通常,我们会使用手动拼接或借助库(如 moment.js
或现代的 Intl.DateTimeFormat
API)来格式化日期
示例:
const date = new Date();
const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
console.log(formattedDate); // 输出: 2024-10-20
5. 常见问题与解决方案
-
月份从 0 开始问题
- 在
Date
对象中,月份是从 0 到 11 的值,0 表示 1 月,11 表示 12 月
所以格式化日期的时候,要记得在月份的数字上+1
- 在
-
时区问题
-
问题描述:
Date
对象默认使用系统的本地时区, -
然而作为系统中的统一时间标准。无论服务器、客户端还是数据库
所有时间都应该是使用 UTC 时间,然后根据需要转换为本地时间 -
解决方法:
UTC 方法
使用
getUTCDate()
、getUTCMonth()
和getUTCFullYear()
方法获取 UTC 时间const localDate = new Date(); console.log('本地时间:', localDate); // 本地时间 // 获取 UTC 时间 const utcYear = localDate.getUTCFullYear(); const utcMonth = (localDate.getUTCMonth() + 1).toString().padStart(2, '0'); // 月份从0开始 const utcDate = localDate.getUTCDate().toString().padStart(2, '0'); const formattedUTCDate = `${utcYear}-${utcMonth}-${utcDate}`; console.log('UTC 时间:', formattedUTCDate); // 输出 UTC 时间
使用
toISOString()
toISOString()
方法可以返回一个 ISO 格式的字符串,表示 UTC 时间const date = new Date(); const isoString = date.toISOString(); console.log('ISO 格式 UTC 时间:', isoString); // 例如:2024-10-20T15:30:00.000Z
使用第三方库
Moment.js
或date-fns
都是和时间操作有关的第三方库,以后有时间详细说说先挖个坑
-
3. 如何判断闰年
- 被4整除的并且不被100整除的年份
- 能够被400整除的年份
示例:
function runYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}
console.log(runYear(2024)); // 输出: true
console.log(runYear(2023)); // 输出: false
二、正则表达式 (RegExp)
1. 正则表达式的定义
正则表达式是一种用于匹配文本模式的表达式
它可以用来验证输入、查找和替换文本、提取信息
2. 创建正则表达式
-
使用字面量创建
const regex = /hello/;
-
使用
RegExp
构造函数const regex = new RegExp('hello');
3. 匹配常用字符
正则表达式中定义匹配规则的常用字符:
.
: 匹配除换行符以外的任意字符\d
: 匹配一个数字(0-9)\D
: 匹配一个非数字字符\w
: 匹配一个字母、数字或下划线字符\W
: 匹配一个非字母、非数字、非下划线字符\s
: 匹配空白字符(空格、制表符等)\S
: 匹配非空白字符^
: 匹配字符串的开头$
: 匹配字符串的结尾*
: 匹配前面的子表达式零次或多次+
: 匹配前面的子表达式一次或多次?
: 匹配前面的子表达式零次或一次{n,m}
: 匹配前面的子表达式至少 n 次,至多 m 次
4. 常用方法
-
test(): 测试字符串是否匹配正则表达式,返回
true
或false
const regex = /hello/; console.log(regex.test('hello world')); // 输出: true console.log(regex.test('hi there')); // 输出: false
-
match(): 在字符串中查找匹配项,返回一个数组
const str = 'hello world'; const result = str.match(/hello/); console.log(result); // 输出: ['hello']
-
replace(): 替换匹配的子字符串
const str = 'hello world'; const newStr = str.replace(/world/, 'JavaScript'); console.log(newStr); // 输出: 'hello JavaScript'
-
split(): 使用正则表达式分割字符串
const str = 'apple, banana, cherry'; const fruits = str.split(/, /); console.log(fruits); // 输出: ['apple', 'banana', 'cherry']
5. 正则表达式中的标志(Flags)
g
: 全局匹配(查找所有匹配项,而不是找到第一个就停止)i
: 不区分大小写匹配m
: 多行匹配s
: 允许.
匹配换行符u
: 支持 Unicodey
: 粘性匹配,从目标字符串的当前位置开始匹配
示例:
const regex = /hello/gi; // 匹配所有不区分大小写的 'hello'
console.log('Hello hello HEllO'.match(regex)); // 输出: ['Hello', 'hello', 'HEllO']
6. 常见问题与解决方案
1. 贪婪匹配与惰性匹配
- 问题描述:正则表达式默认使用贪婪匹配,
贪婪匹配会尽可能多的匹配字符,而有的时候我们仅需要惰性匹配,只匹配最小范围即可 - 解决方案:使用
?
将匹配变为惰性匹配。
const str = '123abc456';
console.log(str.match(/\d+/)); // 输出: ['123456'] (贪婪匹配)
console.log(str.match(/\d+?/)); // 输出: ['1'] (惰性匹配)
2. 转义字符
- 问题描述:特殊字符(比如
.
、*
等),需要使用反斜杠\
进行转义 - 解决方案:在需要匹配这些特殊字符时,用
\
进行转义
const str = '3.14';
const regex = /\./; // 定义一个正则表达式变量 ,用于匹配 '.'
console.log(regex.test(str)); // 匹配到了,输出: true
3. 跨行匹配
- 问题描述:默认情况正则表达式不会匹配换行符。
- 解决方案:使用
s
标志来匹配换行符。
const str = 'hello\nworld';
const regex = /hello.world/s;
console.log(regex.test(str)); // 输出: true
三、错误对象 (Error)
1. 错误对象的定义
当程序运行时遇到错误,JavaScript 会创建一个错误对象,并停止当前代码的执行
2. 创建错误对象
2.1 使用 Error
构造函数
const error = new Error('错误信息');
console.log(error.name); // 输出: Error
console.log(error.message); // 输出: 错误信息
2.2 错误对象的分类
SyntaxError
:语法错误ReferenceError
:引用未定义的变量TypeError
:数据类型不匹配RangeError
:数值超出范围URIError
:URI 处理函数使用不当EvalError
:与eval()
函数相关的问题(很少使用)
示例:
const typeError = new TypeError('数据类型错误');
console.log(typeError.name); // 输出: TypeError
console.log(typeError.message); // 输出: 数据类型错误
3. try…catch 语句
为了处理代码中的错误,我们可以使用 try...catch
语句
try
中的代码会被正常执行,如果遇到错误自动转换到 catch
中
示例:
try {
// 可能会产生错误的代码
let result = someUndefinedFunction();
} catch (error) {
// 捕获并处理错误
console.log('发生错误:', error.message);
}
4. finally
在 try...catch
语句中,我们可以添加一个 finally
无论是否发生错误,finally
块中的代码都会被执行,用于释放资源
示例:
try {
console.log('执行');
throw new Error('错误');
} catch (error) {
console.log('捕获到错误:', error.message);
} finally {
console.log('无论如何都会执行的代码');
}
5. 自定义错误
在实际编程中,有的时候需要抛出自定义的错误
可以通过 throw
关键字抛出一个错误对象,抛出自己定义的错误类型。
示例:
function checkNumber(num) {
if (typeof num !== 'number') {
throw new TypeError('传入的参数必须是数字');
}
console.log('参数是一个数字');
}
try {
checkNumber('abc'); // 传入非数字,触发错误
} catch (error) {
console.log('错误信息:', error.message); // 输出: 错误信息: 传入的参数必须是数字
}
6. 错误类型及应用场景
以下是一些常见的错误类型以及它们的应用场景:
-
SyntaxError(语法错误):
try { eval('console.log("Hello World)'); // 引号缺失,语法错误 } catch (e) { console.log('语法错误:', e.message); }
-
ReferenceError(引用错误):尝试引用未定义的变量
try { console.log(undefinedVariable); // 变量未定义 } catch (e) { console.log('引用错误:', e.message); }
-
TypeError(类型错误):在不正确的数据类型上执行操作
try { null.someMethod(); // null 上调用方法会引发类型错误 } catch (e) { console.log('类型错误:', e.message); }
-
RangeError(范围错误):数值超出了允许范围
try { new Array(-1); // 数组长度不能为负数 } catch (e) { console.log('范围错误:', e.message); }
-
URIError(URI 处理错误):错误使用 URI 函数
try { decodeURIComponent('%'); // 无效的 URI 字符 } catch (e) { console.log('URI 错误:', e.message); }
拓展阅读:Map / Set
Map
和 Set
是 ES6 中的新特性,
用于处理集合类的数据结构,功能比传统的对象和数组更多
1. Map 数据类型
Map
是一个键值对集合,与普通对象不同的是
Map
允许任何类型的值(对象、原始类型)作为键
1.1 Map 创建
可以使用 new Map()
创建一个新的 Map
对象:
const map = new Map();
1.2 操作 Map
-
添加键值对: 使用
set
方法。map.set('name', 'Alice'); map.set(42, 'The answer'); map.set(true, 'Yes');
-
获取值: 使用
get
方法。console.log(map.get('name')); // 输出: Alice console.log(map.get(42)); // 输出: The answer
-
检查键是否存在: 使用
has
方法。console.log(map.has('name')); // 输出: true console.log(map.has('age')); // 输出: false
-
删除键值对: 使用
delete
方法。map.delete(42); console.log(map.has(42)); // 输出: false
-
获取键值对数量: 使用
size
属性。console.log(map.size); // 输出: 2
-
清空所有键值对: 使用
clear
方法。map.clear(); console.log(map.size); // 输出: 0
1.3 Map 的应用场景
- 需要使用复杂类型(比如对象)作为键的时候
- 需要保证键的顺序(
Map
会按插入顺序保持键值对) - 需要频繁地查询、更新、删除键值对时,
Map
比普通对象性能更好
2. Set 数据类型
Set
是一种无重复值的集合
它允许存储任何类型的唯一值(原始值或对象引用)
2.1 Set 创建
可以使用 new Set()
创建一个新的 Set
对象:
const set = new Set();
2.2 操作 Set
-
添加值: 使用
add
方法set.add(1); set.add(2); set.add(2); // 重复值不会被添加 set.add('Hello');
-
检查值是否存在: 使用
has
方法console.log(set.has(2)); // 输出: true console.log(set.has(3)); // 输出: false
-
删除值: 使用
delete
方法set.delete(1); console.log(set.has(1)); // 输出: false
-
获取元素数量: 使用
size
属性console.log(set.size); // 输出: 2
-
清空所有值: 使用
clear
方法set.clear(); console.log(set.size); // 输出: 0
2.3 Set 的应用场景
- 去重操作:将数组中的重复元素移除。
const numbers = [1, 2, 2, 3, 4, 4, 5]; const uniqueNumbers = [...new Set(numbers)]; console.log(uniqueNumbers); // 输出: [1, 2, 3, 4, 5]
3. Map 和 Set 的区别
特性 | Map | Set |
---|---|---|
数据结构 | 键值对集合 | 唯一值集合 |
数据存储 | 存储键值对,每个键是唯一的 | 仅存储值,所有值都是唯一的 |
键类型 | 允许任何类型(对象、基本类型)作为键 | 不需要键,直接存储唯一值 |
常见用途 | 高效键值对存储和查找 | 数据去重、检查唯一值集合 |
4. WeakMap 和 WeakSet
WeakMap
: 与Map
类似,但键必须是对象,且对象引用是弱引用WeakSet
: 与Set
类似,但只能存储对象,且对象引用是弱引用
4.1 强引用和弱引用:
强引用会阻止垃圾回收,而弱引用不会
简单来说,如果一个对象被强引用指向了,对象所属的内存就会一直保留
反过来说,如果一个对象只被弱引用指向,那么该对象所属的内存就会被定期清理
4.2 WeakMap 和 WeakSet 的使用场景
这两个数据类型可以有效地管理内存
特别是在处理大量对象的时候,弱引用能减少不必要的内存占用
可以在一些临时储存或者跟踪对象的时候使用
标签:const,log,匹配,数据类型,Date,进阶篇,new,零学起,console From: https://blog.csdn.net/2401_87242367/article/details/143109634