在ES6
之前如果我们想要将变量动态的放入到字符串中
是非常麻烦的
而在ES6
中提供了模版字符串
的写法
这种写法可以轻松实现上述需求
模版字符串
与普通字符串最大区别在于普通字符串用""
或''
包裹,而模版字符串则用``包裹
以下是一个简单的模版字符串
var name = "张三"
var age = "20"
var str = `name:${name};age:${age}`
我们可以在``中通过${}
来动态的放入内容
${}
中不仅能放变量
,还能放表达式
,乃至运行函数
var name = "张三"
var age = "20"
function foo() {
return "Function foo"
}
var str = `name:${name};age:${age < 18 ? "未成年" : "成年"};${foo()}`
标签模板字符串
是模版字符串的一种更高级的应用形式,它可以通过将模版字符串传入函数
,由函数来解析模版字符串,最后返回被操作过的字符串
,这个函数也被称为标签函数
var name = "张三"
var age = "20"
function foo() {
return "Function foo"
}
function tag(strings, ...args) {
console.log(strings)
console.log(args)
}
tag`name:${name};age:${age < 18 ? "未成年" : "成年"};${foo()}`
控制台打印结果如下
可以看到标签函数
的第一个参数为一个数组
,里面存储着被分割的字符串
,剩下的参数为动态传入的值
这里传入的值是计算之后的值
,而不是原始表达式
其中strings
有一个特殊属性raw
,我们可以通过它来访问原始字符串
而不需转义特殊字符
在ES6
中我们可以在函数参数列表给参数一个默认值
,当这个参数没有传值时默认使用默认值
以下是一个简单的默认值使用
function fn(x = 1, y = 2) {
console.log(x, y)
}
fn()
fn(3, 4)
控制台结果如下
默认值
也可以引用前面已经定义的默认值
function fn(x = 1, y = x + 2) {
console.log(x, y)
}
fn()
fn(3)
fn(3, 4)
控制台结果如下
参数默认值
也可以和参数解构
联系使用
function fn({ x = 1, y = x + 2 } = {}) {
console.log(x, y)
}
fn({})
fn({ x: 3 })
fn({ x: 3, y: 4 })
控制台结果如下
在ES6
以前如果我们想要知道函数被调用时传递了多少参数
就需要使用arguments
关键字
在ES6
之后引入了剩余参数(rest)
这个新语法,它可以将不定数量的参数放入一个数组中
rest
的用法也很简单,只需要在参数前加上...
就行
下面是一个简单的rest
用法
function fn(name = "lisi", ...args) {
console.log(name, ...args)
}
fn()
fn("zhangsan")
fn("zhangsan", 1, 2, 3)
控制台结果如下
可以发现和arguments
最大的不同之处在于arguments
是一个伪数组
,无法使用数组相关的方法,而rest
是一个数组
除了这个区别之外,arguments
和rest
还有以下其它区别
arguments
里存储着全部传入的参数
,rest
只存储着没有形参对应的参数
arguments
是早期ECMAScript
中为了方便获取参数所提供的一个数据结构
,而rest
是为了替代arguments
而推出的rest
必须放在参数列表最后
,否则会报错在ES6
中推出了一种新的函数范式
,箭头函数
以下是一个简单的箭头函数
定义
var fn = () => {
console.log("fn")
}
fn()
在此其中:fn
是函数名,()
中是参数,{}
内部是函数体
需要注意的是,箭头函数
没有显式的原型
,这意味着它没有constructor
,无法通过new
构造对象
箭头函数中也没有绑定this
、arguments
、super
关键字,想要获取箭头函数中传入的全部参数
只能使用rest
展开语法
可以在函数传参
或者数组构造
时,将数组或者字符串
在语法层面展开
还可以在构造字面量对象
时,将对象表达式按键值对
的方式展开
以下是一个关于展开语法
简单的演示
var fn = (x, y, z) => {
console.log(x, y, z)
}
var arr = [1, 2, 3]
fn(...arr)
Symbol
是ES6
中新增的一个基本数据类型
,可用于构造一个独一无二的值
在ES6
之前,我们很难避免因属性名冲突而导致的value覆盖
问题
如我们希望向某个对象中添加一个属性,但这个操作可能会因为原对象中已经存在这个属性而导致value
覆盖的问题
在ES6
中为了解决这个问题于是就推出了Symbol
,由于Symbol
构造出来的值是唯一
的,所以可以用这个值来当对象的属性名
而不用担心覆盖
问题
以下是Symbol
的一个简单演示
var s1 = Symbol()
var s2 = Symbol("s2")
var obj = {
[s1]: "s1",
[s2]: "s2"
}
console.log(obj)
控制台结果如下
需要注意的是通过Symbol
构建的变量想要作为属性名需要用[]
括起来
每次调用Symbol
所创建的值都是唯一
的,如果我们需要创建两个相同
的Symbol
值可以用for
方法,也可以通过keyFor
的方法拿到key
值
var s1 = Symbol.for("fn")
var s2 = Symbol.for("fn")
console.log(s1 == s2)
var key1 = Symbol.keyFor(s1)
var key2 = Symbol.keyFor(s2)
console.log(key1, key2)
控制台结果如下
Set
是ES6
中新增的数据结构
,可以用来保存数据
,类似于数组
,但是Set
中的元素不能重复
Set
只能通过new
来构造
Set
中可以存放基本数据类型
和复杂数据类型
以下是一个简单的Set
例子
var set = new Set();
set.add(1)
set.add(2)
set.add(3)
var set2 = new Set([4, 5, 6])
var arr = [1, 2, 2, 2, 3, 4]
var set3 = new Set(arr)
console.log(set, set2, set3)
控制台结果如下
可以看到Set
也能用来给数组去重
Set
的常用方法有以下几个
add()
:向指定Set
添加某个元素
,返回这个Set
本身delete()
:将指定Set
中的指定元素删除,成功返回true
,失败返回false
has()
:判断指定Set
中是否有指定元素,如果有就返回true
,失败就返回false
clear()
:清空指定Set
,无返回值forEach()
:同其他forEach
Set
同样支持for...of
遍历
weakSet
和Set
类似,都不能存储相同的元素
,不同的是weakSet
只能存储对象
或符号类型
weakSet
中存储的是一定会被删除的元素
,所以其只能存储对象
或符号
weakSet
对元素的引用是弱引用
,这意味着如果没有其他对weakset引用的对象的引用存在,则此对象将会被GC
weakSet
的定义和Set
类似,只能通过new
来构造
var weak = new WeakSet()
weakSet
的方法比Set
少了clear
和forEach
,因为weakSet
是不可枚举
的
add()
:向指定weakSet
中添加指定元素,返回指定的weakSet
对象delete()
:将指定的weakSet
中指定的元素删除,成功返回true
,失败返回false
has()
:判断指定weakSet
中指定的元素是否存在,存在返回true
,失败返回false
Map
结构用来存储映射关系
,在ES6
之前我们可以通过对象
来存储映射关系
,但对象只能将字符串
来作为key,Map则可以将对象
也作为key
以下是一个简单的Map
示例
var obj1 = {
key: "value1"
}
var obj2 = {
key: "value2"
}
var map = new Map()
map.set(obj1, "obj1")
map.set(obj2, "obj2")
map.set("aaa", "aaa")
map.set(1, 1)
var map2 = new Map([
[obj1, "value1"],
[obj2, "value2"],
[1, 1],
["aaa", "aaa"]
])
console.log(map, map2)
console.log(map2.size)
控制台结果如下
我们可以通过size
这个属性来访问map
中存储了多少映射关系
Map
的常用方法有以下几个
set(key,value)
:向指定Map
中添加指定映射关系,返回指定的Map
对象get()
:在指定Map
中通过指定的key
寻找对应的value
has()
:在指定的Map
中判断指定的key
是否存在,存在返回true
,不存在返回false
delete()
:在指定的Map
中删除指定key
的映射关系,成功返回true
,失败返回false
clear()
:清空指定Map
,无返回值forEach()
:同其他forEach
Map
同样也可以通过for...of
遍历
weakMap
和weakSet
类似,weakMap
只能由对象
类型来组成key
,并且weakMap
的key
对其对象是弱引用
,与weakSet
相同,weakMap
同样不能枚举
var weak = new WeakMap()
weakMap
常用方法有以下几个
set(key,value)
:向指定weakMap
中添加指定映射关系
,返回指定的weakMap
对象get()
:在指定weakMap
中通过指定的key
寻找对应的value
has()
:在指定的weakMap
中判断指定的key
是否存在,存在返回true
,不存在返回false
delete()
:在指定的weakMap
中删除指定key
的映射关系,成功返回true
,失败返回false
关于Promise
的具体用法可以看我这篇博客
Promise
关于Proxy
和Reflect
可以看我这篇博客
未动笔,未来可寄
关于迭代器
与生成器
可以看我这篇博客
迭代器与生成器
用来判断元素是否在数组中,如果存在就返回true
,不存在就返回false
var arr = [1, 2, 3, 4]
console.log(arr.includes(5))
console.log(arr.includes(4))
控制台结果如下
用来计算乘方
var num1 = Math.pow(2, 2)
var num2 = 2 ** 2
我们可以通过这个来获取对象的所有值
var obj = {
name: "zhangsan",
age: 18,
sex: "男"
}
console.log(Object.values(obj))
console.log(Object.values("aaa"))
控制台结果如下
Object.entries
可以获取到一个数组
,数组中会存放可枚举属性的键值对数组
var obj = {
name: "zhangsan",
age: 18,
sex: "男"
}
console.log(Object.entries(obj))
padStart
用于对字符串首部填充
padEnd
用于对字符串尾部填充
var message = "hello world!"
console.log(message.padStart(15, "#"))
console.log(message.padEnd(15, "#"))
我们可以通过trim
来清除字符串首尾的空格,也可以通过trimStart
来清除字符串首部空格,trimEnd
来清除字符串尾部的空格
var str = " hello world "
console.log("aaa" + str.trim() + "aaa")
console.log("aaa" + str.trimStart() + "aaa")
console.log("aaa" + str.trimEnd() + "aaa")
flat
方法可以指定一个深度
来遍历多维数组
,并将遍历到元素组成一个新数组
返回
var arr = [[1, 1, 1], 2, [3, [4, 4]]]
console.log(arr.flat(1))
console.log(arr.flat(2))
flatMap
会将数组中的每个元素
应用于给定的回调函数
,再将得到的结果组成一个新数组
,并将这个新数组展开一层
,可以理解为先将数组
进行Map
操作在进行flat(1)
操作,比单独调用这两个方法更加高效
var arr = [[1, 1, 1], 2, [3, [4, 4]]]
var arr2 = arr.flatMap(function (res) {
return res
})
console.log(arr2)
我们可以将通过Object.entries
得到的数组
重新转化为对象
var obj = {
name: "zhangsan",
age: 18,
sex: "男"
}
var entries = Object.entries(obj)
var obj2 = Object.fromEntries(entries)
console.log(obj2)
一个新的数据类型
,可以表示以前js
无法表示的大整数
用法很简单,只需要在数字后面加上n
就行
var num = 99999999999999999999999999
var num2 = 99999999999999999999999999n
console.log(num)
console.log(num2)
空值合并运算符(??)
是一个逻辑运算符
当左侧的操作数为null
或者undefined
时,返回其右侧操作数
,否则返回左侧操作数
可选链
具体来说应该是一个新运算符(?.)
它可以读取对象
所访问的属性
是否为空
,并且返回undefined
,不同与.
运算符,当它访问到不存在的属性时会报错
,而?.
不会
var obj = {
name: "zhangsan",
friend: {
name: "lisi",
friend: {
name: "wangwu"
}
}
}
console.log(obj?.friend?.friend?.friend?.name)
console.log(obj.friend.friend.friend.name)
因为js
运行环境不同,其全局对象
往往也会不同,我们就需要使用不同的关键字来访问全局对象
新标准中规定了globalThis
这个关键字用于访问全局对象
FinalizationRegistry
对象允许被注册
的对象
被回收
时执行设定好的回调函数
通过调用register
来设定注册对象
以及传入回调函数的参数
var registry = new FinalizationRegistry(function (res) {
console.log(`${res}被回收了`)
})
let obj1 = {
key: "value"
}
let obj2 = {
key: "value"
}
registry.register(obj1, "obj1")
registry.register(obj2, "obj2")
obj1 = null
obj2 = null
当我们将一个对象赋值
给另一个引用
的话这个引用
默认是一个强引用
,如果我们需要这个引用
是弱引用
的话需要用WeakRef
var obj1 = {
key: "value"
}
var obj2 = new WeakRef(obj1)
Object.hasOwn
用于判断一个对象
中是否有指定的属性
var obj1 = {
key: "value"
}
console.log(Object.hasOwn(obj1, "key"))
console.log(Object.hasOwn(obj1, "name"))
其中hasOwn
的第一个参数为需要判断的对象
,第二参数为需要判断的key
新标准中针对class
的成员字段
提供了新的修饰符
static
修饰符表示此属性/方法
只能通过类
来调用
在字段名
前加#
号代表此字段
是私有
的
可以使用in
运算符检查私有字段
是否存在。当私有字段存在时返回true
,否则返回false