这部分内容开始对JS中其他的内建对象进行补充。主要包括:结构复制、序列化、Map、Set、Date、包装类、String、正则表达式以及垃圾回收(GC)
案例:将arr分别赋值给a,b,c
基本方法:
const arr = ["孙悟空", "猪八戒", "沙和尚"]
let a,
b,
c
a = arr[0]
b = arr[1]
c = arr[2]
console.log(a,b,c)

使用对象解构:
推荐在结构赋值前面手动加分号,防止编译器解析出问题
const arr = ["孙悟空", "猪八戒", "沙和尚"]
let a,
b,
c
;[a, b, c] = arr // 解构赋值
console.log(a,b,c)

但是一般使用的时候是声明和赋值在一起的(声明同时结构),但是如果前面参数比后面数组多,会被赋值undefined
let [d, e, f, g] = ["唐僧", "白骨精", "蜘蛛精", "玉兔精"]
console.log(d, e, f, g)
;[d, e, f, g] = ["唐僧", "白骨精", "蜘蛛精"]
console.log(d, e, f, g)

在赋值的时候给定默认值,就可以防止其出现undefined,如果设置了默认值,同时在数组解构的时候可以覆盖掉这个值,那么最终这个值存的是数组中的对应元素
有值就赋值,没有值就用默认值
;[d, e, f=73, g=10] = ["唐僧", "白骨精", "蜘蛛精"]
console.log(d, e, f, g)

在上面的例子中,g开始有值,但是在结构后又变成undefined了,我们想要的效果是如果可以赋值就赋值,不能赋值就用原来的,这样就可以通过下面这样设置来达到效果
let [d, e, f, g] = ["唐僧", "白骨精", "蜘蛛精", "玉兔精"]
console.log(d, e, f, g)
;[d, e, f, g=g] = ["唐僧", "白骨精", "蜘蛛精"]
console.log(d, e, f, g)

解构数组时,可以使用…来设置获取多余的元素
let [n1, n2, ...n3] = [4, 5, 6, 7]
console.log(n1, n2, n3)

function fn() {
return ["二郎神", "猪八戒"]
}
let [name1, name2] = fn() // "二郎神", "猪八戒"
let a1 = 10
let a2 = 20
// 原来的做法
let temp = a1
a1 = a2
a2 = temp
// 解构赋值
;[a1, a2] = [a2, a1] // [20, 10]
交换数组中两个元素的位置
const arr2 = ["孙悟空", "猪八戒"]
;[arr2[0], arr2[1]] = [arr2[1], arr2[0]]
const arr3 = [["孙悟空", 18, "男"], ["猪八戒", 28, "男"]]
let [[name, age, gender], obj] = arr3
console.log(name, age, gender)
console.log(obj)

const obj = { name: "孙悟空", age: 18, gender: "男" }
let { name, age, gender } = obj // 声明变量同时解构对象
console.log( name, age, gender)

这个必须得在解构的时候用括号括起来,不然会将大括号解析为代码块,然后会报错
const obj = {name: "孙悟空", age: 18, gender: "男"}
let name, age, gender
;({name, age, gender} = obj)
console.log( name, age, gender)

const obj = { name: "孙悟空", age: 18, gender: "男" }
let { address } = obj
console.log(address)

const obj = { name: "孙悟空", age: 18, gender: "男" }
// 设置别名
let {name: a, age: b, gender: c} = obj
console.log(a, b, c)

const obj = { name: "孙悟空", age: 18, gender: "男" }
// 设置默认值
let {name: a, age: b, gender: c, address: d = "花果山"} = obj
console.log(a, b, c, d)

const obj = {
name: "孙悟空",
age: 18,
}
// 将obj转换为JSON字符串
const str = JSON.stringify(obj) //JSON.stringify() 可以将一个对象转换为JSON字符串
const obj2 = JSON.parse(str) // JSON.parse() 可以将一个JSON格式的字符串转换为JS对象
console.log(typeof str, str)
console.log(typeof obj2, obj2)

,
const obj = {
"name":"孙悟空",
'age':18,
[Symbol()]:"哈哈",
[obj2]:"嘻嘻"
}

const map = new Map()
map.set("name", "孙悟空")
map.set(obj2, "呵呵")
map.set(NaN, "哈哈哈")
map.delete(NaN)
// map.clear()
console.log(map)
console.log(map.get("name"))
console.log(map.has("name"))

map.size() 获取map中键值对的数量map.set(key, value) 向map中添加键值对map.get(key) 根据key获取值map.delete(key) 删除指定数据map.has(key) 检查map中是否包含指定键map.clear() 删除全部的键值对map.keys() 获取map的所有的keymap.values() 获取map的所有的value方法一:使用方法Array.from(map)
const map = new Map()
map.set("name", "孙悟空")
map.set("age", 18)
map.set({}, "呵呵")
// 将map转换为数组
const arr = Array.from(map) // [["name","孙悟空"],["age",18]]
const arr = [...map]
console.log(arr)

方法二:使用解构符
推荐这种方法,写法更简便
const map = new Map()
map.set("name", "孙悟空")
map.set("age", 18)
map.set({}, "呵呵")
// 将map转换为数组
const arr = [...map]
console.log(arr)

const map2 = new Map([
["name", "猪八戒"],
["age", 18],
[{}, () => {}],
])
console.log(map2)

方法一:使用for-of
const map = new Map()
map.set("name", "孙悟空")
map.set("age", 18)
map.set({}, "呵呵")
for (const [key, value] of map) {
// const [key, value] = entry
console.log(key, value)
}
方法二:使用forEach
const map = new Map()
map.set("name", "孙悟空")
map.set("age", 18)
map.set({}, "呵呵")
map.forEach((key, value)=>{
console.log(key, value)
})
new Set():构造空Setnew Set([...]):从数组构造const set = new Set()
// 向set中添加数据
set.add(10)
set.add("孙悟空")
set.add(10)
console.log(set)

size() 获取数量add() 添加元素has() 检查元素delete() 删除元素方法一:for-of
const set = new Set()
// 向set中添加数据
set.add(10)
set.add("孙悟空")
set.add(10)
for (const item of set) {
console.log(item)
}

方法二:forEach
const set = new Set()
// 向set中添加数据
set.add(10)
set.add("孙悟空")
set.add(10)
set.forEach(item => {
console.log(item)
})

const arr2 = [1, 2, 3, 2, 1, 3, 4, 5, 4, 6, 7, 7, 8, 9, 10]
const set2 = new Set(arr2)
console.log([...set2])

常量:
Math.PI 圆周率Math.e 自然对数方法:
Math.abs() 求一个数的绝对值
Math.min() 求多个值中的最小值
Math.max() 求多个值中的最大值
Math.pow() 求x的y次幂
Math.sqrt() 求一个数的平方根
Math.floor() 向下取整
Math.ceil() 向上取整
Math.round() 四舍五入取整
Math.trunc() 直接去除小数位
Math.random() 生成一个0-1之间的随机数(前开后闭)
let result = Math.abs(10)
result = Math.abs(-10)
result = Math.min(10, 20, 30, 44, 55, -1)
result = Math.max(10, 20, 30, 44, 55, -1)
result = Math.pow(4, 2) // 4 ** 2
result = Math.sqrt(4) // 4 ** .5
result = Math.floor(1.2)
result = Math.ceil(1.2)
result = Math.round(1.4)
result = Math.trunc(1.5)
Math.round(Math.random() * x)Math.floor(Math.random() * (x + 1))Math.round(Math.random() * (y-x) + x)// 生成0-5之间的整数
result = Math.round(Math.random() * 5)
// 生成11-20之间的整数
result = Math.round(Math.random() * 9 + 11)
创建Date对象
let d = new Date() // 直接通过new Date()创建时间对象时,它创建的是当前的时间的对象
console.log(d)

getFullYear() 获取4位年份getMonth() 返当前日期的月份(0-11)getDate() 返回当前是几日getDay() 返回当前日期是周几(0-6) 0表示周日getHours 返回当前小时getMinutes 返回当前分钟getSeconds 返回秒getTime() 返回当前日期对象的时间戳
方法一
// 月/日/年 时:分:秒
let d = new Date("12/20/1998")
console.log(d)

方法二
// 年-月-日T时:分:秒
let d = new Date("2020-12-30")
console.log(d)

方法三
推荐使用这种方式创建
月从0开始记数
至少需要传两个参数
// new Date(年份, 月, 日, 时, 分, 秒, 毫秒)
let d = new Date(2020, 0, 1, 13, 45, 33)
console.log(d)

方法四
使用时间戳
let timeNow = new Date().getTime()
console.log(timeNow) // 获取当前的时间戳
let d = new Date(timeNow)
console.log(d)

// 将日期转换为本地的字符串
console.log(d.toLocaleDateString())
// 将时间转换为本地的字符串
console.log(d.toLocaleTimeString())
// 将时间日期都转
console.log(d.toLocaleString())

toLocaleString()
可以将一个日期转换为本地时间格式的字符串
参数
描述语言和国家信息的字符串
需要一个对象作为参数,在对象中可以通过对象的属性来对日期的格式进行配置
"long" (e.g., Thursday)"short" (e.g., Thu)"narrow" (e.g., T). Two weekdays may have the same narrow style for some locales (e.g. Tuesday’s narrow style is also T)."numeric" (e.g., 2012)"2-digit" (e.g., 12)"numeric" (e.g., 3)"2-digit" (e.g., 03)"long" (e.g., March)"short" (e.g., Mar)"narrow" (e.g., M). Two months may have the same narrow style for some locales (e.g. May’s narrow style is also M)."numeric" (e.g., 1)"2-digit" (e.g., 01)
在JS中,除了直接创建原始值外,也可以创建原始值的对象,也就是通过对象的时候去创建原始值
new String() 可以创建String类型的对象new Number() 可以创建Number类型的对象new Boolean() 可以创建Boolean类型的对象但是千万不要这么做
let str = new String("hello")
let num = new Number(11)
let bool = new Boolean(true)
let bool2 = new Boolean(true)
console.log(bool == bool2)

上面这种情况比较的是两个对象,所以比较的就是地址,调用两次new创建的对象肯定不是指向同一对象,所以尽量不要使用这种方式
JS中一共有五个包装类
String --> 字符串包装为String对象Number --> 数值包装为Number对象Boolean --> 布尔值包装为Boolean对象BigInt --> 大整数包装为BigInt对象Symbol --> 符号包装为Symbol对象通过包装类可以将一个原始值包装为一个对象,当我们对一个原始值调用方法或属性时,JS解释器会临时将原始值包装为对应的对象,然后调用这个对象的属性或方法
由于原始值会被临时转换为对应的对象,这就意味着对象中的方法都可以直接通过原始值来调用
这个功能是留给js自己处理的,尽量不要自己调用new生成新对象
let num = 11
num = num.toString()
console.log(num)

字符串其本质就是一个字符数组,所以字符串的很多方法都和数组是非常类似的
"hello" --> ["h", "e", "l", "l", "o"]
length 获取字符串的长度
let str = "hello"
str.length

字符串[索引] 获取指定位置的字符
let str = "hello"
str[1]

根据索引获取字符,可以接受负索引
let str = "hello"
console.log(str.at(0))
console.log(str.at(-1))
console.log(str.at(-2))

根据索引获取字符
不支持负数,传入负数返回的是空串
let str = "hello"
console.log(str.charAt(0))

用来连接两个或多个字符串
不会破坏原来的字符串,会生成新字符串
和
+效果一样,推荐使用+
let str = "hello"
console.log(str.concat(" ", "world"))

let str = "hello hello how are you"
console.log(str.includes("hello"))
console.log(str.includes("ttt"))
console.log(str.includes("hello", 10))

查询字符串中是否包含某个内容,并返回下标,如果没有的话返回-1
第二个参数是查找的起始,不传默认为0
let str = "hello hello how are you"

检查一个字符串是否以指定内容开头或者结尾的
let str = "hello hello how are you"

通过在开头或者结尾添加指定的内容,使字符串保持某个长度
如果穿进去的第一个参数比
str.length少,则不做任何操作
str = "100"
console.log(str.padStart(7, "0"))
console.log(str.padEnd(7, "0"))

使用一个新字符串替换一个指定内容
str = "hello hello how are you"
let result = str.replace("hello", "abc")
console.log(result)
str = "hello hello how are you"
result = str.replaceAll("hello", "abc")
console.log(result)

使用正则表达式替换
通过指定模式
g可以实现全部替换

对字符串进行切片
substring会自动判断参数,如果第一个参数比第二个参数大,则会自动交换参数位置,slice不会
str = "hello hello how are you"
result = str.slice(12, 15)
result = str.slice(15, 12)
result = str.substring(12, 15)
result = str.substring(15, 12)

str.split():用来将一个字符串拆分为一个数组
str.join():用来将数组拼接为字符串
str = "abc@bcd@efg@jqk"
result = str.split("@")
result = result.join("@"")

根据正则表达式拆分

将字符串转为大写或小写
str = "abcdABCD"
result = str.toLowerCase()
result = result.toUpperCase()

str.trim():去除字符串的前后空格str.trimStart():去除开始空格str.trimEnd():去除结束空格str = " ab c "
str.trim()
str.trimStart()
str.trimEnd()

可以去搜索符合正则表达式的内容第一次在字符串中出现的位置

str.match():根据正则表达式去匹配字符串中符合要求的内容str.matchAll():根据正则表达式去匹配字符串中符合要求的内容(必须设置g 全局匹配),返回的是一个迭代器str.match()可以通过设置全局模式g来匹配所有符合的字符串,并以数组的形式返回

str.matchAll()如果不使用全局模式的话会报错,返回的是一个迭代器,使用for-of遍历可以打印结果

通过构造函数创建:new RegExp()
可以接收两个参数(字符串) 1.正则表达式 2.匹配模式
使用这种方式js编译器会自动将我们的这种写法去转化和字面量相同的方式
优势:可以传递变量,动态生成自责表达式
let reg = new RegExp("a", "i") // 通过构造函数来创建一个正则表达式的对象
console.log(reg)

使用字面量来创建:
// 创建和上面相同的正则
let reg = /a/i
console.log(reg)

使用构造函数的形式需要考虑转义字符,在字面量中可以直接写
let reg = /\w/
reg = new RegExp("\\w") // 如果只写 \w 的话会转义成 w,就表示字母w
let str = "a"
let reg = new RegExp("a")// 表示检查一个字符串中是否含有a
// let reg = /a/ // 也可以使用这种方式定义
let result = reg.test(str) // true
result = reg.test("b") // false
result = reg.test("abc") // true
result = reg.test("bcabc") // true
在正则表达式中大部分字符都可以直接写
| 在正则表达式中表示或(整体的或)
/abc|bcd/表示有abc或者bcd这两个字符串[] 表示或(字符集)
[^] 表示除了
[^x] 除了x. 表示除了换行外的任意字符
在正则表达式中使用\作为转义字符
使用括号进行分组
其他的字符集
\w 任意的单词字符,相当于 [A-Za-z0-9_]
\W 除了单词字符,相当于 [^A-Za-z0-9_]
\d 任意数字,相当于 [0-9]
\D 除了数字,相当于 [^0-9]
\s 空格
\S 除了空格
\b 单词边界
\B 除了单词边界
开头和结尾
^ 表示字符串的开头
$ 表示字符串的结尾例子
量词
+一个以上,相当于{1,}*任意数量的a? 0-1次,相当于{0,1}使用re.exec()获取字符串中符合正则表达式的内容
案例:对于str = "abcaecafcacc"提取出str中符合axc格式的内容
默认情况下只会匹配第一个,通过设置模式
g来开启全局匹配
let str = "abcaecafcacc"
let re = /a([a-z])c/g
let result = re.exec(str)
console.log(result)
不开启全局匹配g模式,每次匹配的都是第一个

开启全局匹配g模式:从头一直匹配到尾

在正则表达式中添加括号表示分组,因此我们现在可以拿到中间的字母(返回数组的第二个元素):
如果有多个括号的话,返回的顺序是按照左括号出现的顺序返回的

获取所有的匹配到的结果,使用循环可以实现
let str = "abcaecafcacc"
let re = /a([a-z])c/g
let result = re.exec(str)
while(result){
console.log(result[0], result[1])
result = re.exec(str)
}

re = /ab/
re.test("abc")

方法一:使用|

方法二:使用[]






垃圾回收(Garbage collection,gc)