ES6知识点记录
标签模板字符串
查看
模板字符串的语法为``
,其中用${}
符号可以传入变量,最终拼接为一个字符串,但``
还可以用于函数的调用,此用法称为标签模板字符串(Tagged Template Literals)。
通过标签模板字符串调用的函数,会将字符串放在一个数组中,位于函数参数的第一位,如果其中用到${}
符号,会将其作为分割符,分割的字符串每一部分作为数组的一项值,而${}
中的表达式结果会作为函数参数,从第二个参数依次传入。
1 | function foo(...args){ |
使用场景:React的styled-componetns库中就用到了标签模板字符串。
函数的默认参数
查看
ES6之后函数的参数可以设置默认值,设置默认值的参数和剩余参数不会记录到Funciton.length中。
推荐将设置默认值的参数放在普通参数后面,剩余参数前面。
因为对于某些语言,设置默认值的参数放在普通参数前会报错。如python,C++等。
函数箭头函数的补充
查看
由于箭头函数没有显式原型prototype,所以不能作为构造函数,使用new创建对象。
箭头函数也不存在this,arguments,super参数。
Symbol的基本使用
查看
我们需要先思考一下Symbol的出现解决了哪些问题?
在ES6之前,对象的属性名都是字符串形式,很容易造成属性覆盖,尤其是在引入外部js文件是,我们很大可能不知道引入的对象存在的属性,一旦对其进行修改,可能会造成意想不到的bug。
而Symbol的出现,解决了这个问题。Symbol可以用来生成一个独一无二的值,并且可以作为字符串的键值。
Symbol的基本使用
1 | const s1 = Symbol() |
对于对象中的Symbol键值是不能通过Object.keys()获取的,但是可以通过Object.getOwnPropertySymbols()获取(只能获取属性为Symbol的键值),且返回的是一个可迭代对象,需要通过迭代才能获取到对应的值。
1 | const obj = { |
前面通过Symbol()
创建的都是独一无二的值,但我们可不可以创建一个重复的Symbol值?
需要用到Symbol.for()
方法,此方法可以传入一个描述参数,只有传入相同的描述参数,才会返回同一个值。且只有同样使用Symbol.for()创建的Symbol值,且描述参数相同,返回的值才相同。
1 | const s1 = Symbol.for() |
并且我们可以通过Symbol.keyFor()
方法来获取Symbol的值对应的描述参数,且只有通过Symbol.for()
方法创建的Symbol,才能用Symbol.keyFor()
方法获取到对应的描述参数。
如果是通过Symbol()
创建的Symbol,则需要用创建的Symbol的description属性来获取对应的描述参数。此属性对用通过Symbol.for()
方法创建的Symbol也可用。
1 | const s1 = Symbol.for('111') |
Set、WeakSet、Map、WeakMap
查看
ES6新增了两种数据结构,分别是Set和Map,以及他们的另外形式WeakSet和WeakMap。
Set
Set和数组类似,可以用于保存数据,但是其中的元素不能重复,所以Set可以用于数组去重。
Set的属性和方法:
-
属性
- size:返回Set中元素的个数。
-
方法
- add(value):向Set中添加元素,返回Set本身。
- delete(value):从Set中删除于value值相等的元素,返回boolean类型。
- has(value):判断set中是否存在某个元素,返回boolean类型。
- clear():清空Set中所有的元素,没有返回值。
- forEach(callback, [, thisArg]):通过forEach遍历set。
-
Set支持使用for of的遍历。
WeakSet
与Set类似的有Weakset,也是内部不能重复的数据结构。
但区别为,WeakSet中只能存放对象,如其中存储的对象为弱引用,即如果没有其他引用对其中存储的某个对象有引用,那么GC可以对该对象回收。
-
方法
- add(value):向WeakSet中添加元素,返回WeakSet本身。
- delete(value):从WeakSet中删除于value值相等的元素,返回boolean类型。
- has(value):判断WeakSet中是否存在某个元素,返回boolean类型。
WeakSet不能遍历,因为对其中存储的仅仅是弱引用,不一定什么时候就被回收了,可能会获取不到。
Map
Map用于存储映射关系,和对象类似,但对象的键只能为字符串或Symbol,如果设定键为对象,会将其转为字符串,导致键值变为{object Object】
的形式,但Map中的键可以设置对象类型。
Map的基本使用
1 | const map = new Map([['name', 'zhangsan'], ['age', 18], [() => { }, 22]]) |
常用方法:
-
属性
- size:返回Map中元素的个数。
-
方法
- set(key, value):向Map中添加元素,返回Map本身。
- get(key):获取与key值相等的元素对应的value值,返回value值。
- delete(key):从Map中删除与key值相等的元素,返回boolean类型。
- has(key):判断Map中是否存在某个元素,返回boolean类型。
- clear():清空Map中所有的元素,没有返回值。
- forEach(callback, [, thisArg]):通过forEach遍历Map。
Map也是可迭代对象,支持for of的遍历。
WeakMap
WeakMap与Map类似,但其中存储的键值只能为对象类型,且也是弱引用。
常见方法:
-
set(key, value):向WeakMap中添加元素,返回WeakMap本身。
-
get(key):获取与key值相等的元素对应的value值,返回value值。
-
delete(key):从WeakMap中删除与key值相等的元素,返回boolean类型。
-
has(key):判断WeakMap中是否存在某个元素,返回boolean类型。
WeakSet与WeakMap的弱引用
对于WeakSet和WeakMap,是ES6之后推出的数据结构,用于实现对对象的存储,但对对象的引用是弱引用。
弱引用是即使存在对对象的引用,但当被引用对象不存在强引用时,会被标记为可回收状态,随后被GC(垃圾回收器)回收。
至于对对象不存在强引用的状态,可以分为两种:
-
当对象离开作用域时
-
但对对象的引用赋值为null时
假设不存在闭包,当代码块中创建了对象,并用WeakSet或WeakMap存储,当代码块执行完毕,EC弹出ECS,且代码块中的对象没有被其他变量引用,此时便标记为为回收状态,存在闭包时,如果对函数返回的闭包状态进行了变量接受,此时对其时强引用,只能手动赋值为null,此时才可被回收。
WeakSet和WeakMap的引用场景:
-
跟踪对象状态
-
添加临时对象
-
减少内存泄漏
跟踪对象状态这一块,能做的操作很多,通过对其的get、set、has方法的组合使用,可以保证对象可用,类似的操作也可以用于避免DOM的事件重复绑定和缓存操作等。
FinalizationRegistry
查看
FinalizationRegistry对象可以让你在对象被来及回收时请求一个回调。
-
FinalizationRegistry 提供了这样的一种方法:当一个在注册表中注册的对象被回收时,请求在某个时间点上调用一个清理回调。(清理回调有时被称为 finalizer )。
-
你可以通过调用register方法,注册任何你想要清理回调的对象,传入该对象和所含的值。
1 | let obj = { name: 'obj' } |
WeakRefs
查看
如果我们默认将一个对象赋值给另一个引用,那么这个对象是一个强引用。如果我们希望是一个弱引用的话,可以使用WeakRef。
1 | let obj = { name: 'obj' } |
method.at()
查看
ES13引入了at方法,用于获取数组和字符串中指定位置的元素或字符。
1 | const arr = ['1', '2', '3'] |
Object.hasOwn(obj, propKey)
查看
ES13在Object中新增了hasOwn静态方法,用于判断一个对象中是否存在某个属性,不包括原型链。
1 | const obj = { name: 'obj' } |
Object.hasOwn和Object.prototype.hasOwnProperty的区别:
-
一个是在静态方法上,一个是在原型对象上。
-
hasOwnProperty在原型对象上,很容易被对象内部重写,因为可能有人不知道有这个方法,从而自定义了一个,对后续造成了影响。
-
对于隐式原型指向null的对象,hasOwnProperty无法进行判断。
- 因为hasOwnProperty是通过原型链找到Object的原型对象调用的,一旦将对象的移除指向Objetc的原型对象时,那么hasOwnProperty就无法调用了。
1 | const obj = { name: 'obj' } |