前言
前端学无止境,努力学习吧,骚年~
这边稍微整理下ES6 至 ES12 常用到的特性,也有可能遗漏,希望大家可以补充,感谢。。Ps(使用新特性需要使用最新版的 bable 就行转义)
ES6(2015)
1. let / const
// let个const没有变量提升,而var有,const一般定义常量
let foo = 'foo'
let foo = 'test' // SyntaxError: Identifier 'foo' has already been declared
const bar = 'bar'
bar = 'test' // TypeError: Assignment to constant variable.
const info = { name: '小方' }
info.name = 'test' // 可以修改, 因为没有修改引用地址,修改的只是引用地址里面的属性,这里涉及到堆栈内存的概念
2. 类(class)
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
eating() {
console.log(this.name + 'eating~')
}
}
const p = new Person('小方', 18)
console.log(p.name)
p.eating()
3. 字面量的增强
const message = 'hello'
const age = 18
const obj = {
// 属性的简写:Property Shorthand
message,
age,
// 方法的简写:Method Shorthand
foo() {
},
// 计算属性名:Computed Property Names
[message + 'world']: 'test'
}
console.log(obj) // { message: 'hello', age: 18, foo: [Function: foo], helloworld: 'test' }
4. 解构Destructuring
// 数组的解构:
const arr = ['js', 'html', 'css']
// 对数组的解构
const [ item1, item2, item3 ] = arr
console.log(item1, item2, item3) // js html css
// 解构后面的元素
const [ , , item4 ] = arr
console.log(item4) // css
// 解构出部分元素,后面放到新的数组中
const [ item5, ...newArr ] = arr
console.log(item5, newArr) // js [ 'html', 'css' ]
// 默认值
const [ item6, item7, item8, item9 = '默认' ] = arr
console.log(item6, item7, item8, item9) // js html css 默认
<------------------------------------------------------------->
// 对象d的解构:
const info = {
name: '小方',
age: 18,
height: 1.88
}
const { name, age, height } = info
console.log(name, age, height) // 小方 18 1.88
// 重命名配合默认值
const { name: newName, address: newAddress = '上海市' } = info
console.log(newName, newAddress) // 小方 上海市
**5. 字符串模板 **
const name = '小方'
const age = 18
const height = 1.88
function foo() {
return 'hello world'
}
console.log(`我的名字叫:${name},我的年龄是:${age},我的身高是:${height},函数:${foo()}`)
// 我的名字叫:小方,我的年龄是:18,我的身高是:1.88,函数:hello world
6. 函数的默认参数
function add(a = 10, b = 20) {
console.log(a + b)
}
add(30, 40) // 70
add() // 30
7. 函数的剩余参数
// 注意剩余参数必须放到最后一个位置,否则会报错
// 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参
// arguments对象不是一个真正的数组,而rest参数是一个真正的数组,可以进行数组的所有操作
// arguments是早期的ECMAScript中为了方便去获取所有的参数提供的一个数据结构,而rest参数是ES6中提供
并且希望以此来替代arguments的;
function foo(num1, num2, ...arg) {
console.log(num1, num2, arg)
}
foo(10, 20, 30, 40, 50, 60) // 10 20 [ 30, 40, 50, 60 ]
8. 函数箭头函数
// 箭头函数内部的this指向的是上层作用域
const foo = () => {
console.log(this) // 指向上层作用域
}
foo()
// 没有原型属性
console.log(foo.prototype) // undefined
// 不能作为构造函数使用
const f = new foo() // TypeError: foo is not a constructor
9. 展开语法
// 数组操作
const arr = ['js', 'html', 'css', 'vue']
const test = 'test'
function foo(a, b , c ,d){
return `${a} - ${b} - ${c} - ${d}`
}
console.log(foo(...arr)) // js - html - css - vue
console.log(foo(...test)) // t - e - s - t
const newArr = [...arr, test ]
console.log(newArr) // [ 'js', 'html', 'css', 'vue', 'test' ]
// 对象(展开运算其实也是个浅拷贝)
const obj = {name: '小方', age: 18, height: 1.88 }
const info = {...obj, address: '上海市', ...arr }
console.log(info)
// {
// '0': 'js',
// '1': 'html',
// '2': 'css',
// '3': 'vue',
// name: '小方',
// age: 18,
// height: 1.88,
// address: '上海市'
// }
10. 数值的表示
// 平时开发中很少用(作为了解)
const num1 = 100 // 十进制
const num2 = 0b100 // 二进制
const num3 = 0o100 // 八进制
const num4 = 0x100 // 十六进制
console.log(num1, num2, num3, num4) // 100 4 64 256
11. Symbol
// Symbol
// Symbol是什么呢?Symbol是ES6中新增的一个基本数据类型,翻译为符号。
// 在ES6之前,对象的属性名都是字符串形式,那么很容易造成属性名的冲突;
// 比如原来有一个对象,我们希望在其中添加一个新的属性和值,但是我们在不确定它原来内部有什么内容的情况下,很容易造成冲突,从而覆盖掉它内部的某个属性;
// Symbol就是为了解决上面的问题,用来生成一个独一无二的值。
// Symbol值是通过Symbol函数来生成的,生成后可以作为属性名;
const s1 = Symbol()
const s2 = Symbol()
console.log(s1 === s2) // false
// (ES2019)中提供了一个描述(description)
const s3 = Symbol('test')
console.log(s3.description) // test
const obj = {
[s1]: 's1',
[s2]: 's2'
}
obj[s3] = 's3'
console.log(obj[s1], obj[s2], obj[s3]) // s1 s2 s3
// 注意:不能通过obj.来获取
// Symbol作为属性名,在遍历/Object.keys是获取不到的
console.log(Object.getOwnPropertySymbols(obj)) // [ Symbol(), Symbol(), Symbol(test) ]
const sKeys = Object.getOwnPropertySymbols(obj)
for (const item of sKeys) {
console.log(obj[item]) // s1 s2 s3
}
12. Set、Map、WeakMap、WeakSet
- 在ES6之前,我们存储数据的结构主要有两种:数组、对象
- 在ES6中新增了另外两种数据结构:Set、Map,以及它们的另外形式WeakSet、WeakMap。
- Set是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是元素不能重复
- 创建Set我们需要通过Set构造函数(暂时没有字面量创建的方式):
- 我们可以发现Set中存放的元素是不会重复的,那么Set有一个非常常用的功能就是给数组去重 Set
const arr = new Set()
arr.add(1)
arr.add(2)
arr.add(3)
console.log(arr) // Set(3) { 1, 2, 3 }
const list = [1, 2, 3, 4, 1, 5, 6, 2, 4]
const arrSet = new Set(list)
console.log(arrSet) // Set(6) { 1, 2, 3, 4, 5, 6 }
const newArr = Array.from(arrSet) // 也可以[ ...arrSet ]
console.log(newArr) // [ 1, 2, 3, 4, 5, 6 ]
// size属性
console.log(arrSet.size) // 6
// add
arrSet.add(10)
console.log(arrSet) // Set(7) { 1, 2, 3, 4, 5, 6, 10 }
// delete
arrSet.delete(10)
console.log(arrSet) // Set(6) { 1, 2, 3, 4, 5, 6 }
// has
console.log(arrSet.has(1)) // true
// clear
// arrSet.clear()
console.log(arrSet) // Set(0) {}
// 对Set进行遍历
arrSet.forEach(item => {
console.log(item) // 1 2 3 4 5 6
})
for (const item of arrSet) {
console.log(item)// 1 2 3 4 5 6
}
WeakSet
- 和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构 那么和Set有什么区别呢?
- 区别一:WeakSet中只能存放对象类型,不能存放基本数据类型;
- 区别二:WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收;
const arr = new WeakSet()
arr.add(1) // TypeError: Invalid value used in weak set
// add(value):添加某个元素,返回WeakSet对象本身
// delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型
// has(value):判断WeakSet中是否存在某个元素,返回boolean类型
Map
// 在我们JavaScript中之前不是能将一个对象作为一个对象的key的,但是Map是可以的
const obj1 = { name: 'obj1' }
const obj2 = { name: 'obj2' }
const map = new Map()
// Map的属性和方法
map.set(obj1, 'obj1')
map.set(obj2, 'obj2')
map.set('name', 'name')
console.log(map) // Map(3) { { name: 'obj1' } => 'obj1', { name: 'obj2' } => 'obj2', 'name' => 'name' }
console.log(map.get(obj1)) // obj1
console.log(map.size) // 3
console.log(map.has('name')) // true
map.delete('name')
// map.clear()
// 也可以遍历
map.forEach((item, key)=>{
console.log(item, key)
// obj1 { name: 'obj1' }
// obj2 { name: 'obj2' }
})
WeakMap
- 和Map类型相似的另外一个数据结构称之为WeakMap,也是以键值对的形式存在的。 那么和Map有什么区别呢?
- 区别一:WeakMap的key只能使用对象,不接受其他的类型作为key;
- WeakMap的key对对象想的引用是弱引用,如果没有其他引用引用这个对象,那么GC可以回收该对象;
const weakMap = new WeakMap()
weakMap.set(1, 'test') // TypeError: Invalid value used as weak map key
WeakMap常见的方法有四个:
set(key, value):在Map中添加key、value,并且返回整个Map对象;
get(key):根据key获取Map中的value
has(key):判断是否包括某一个key,返回Boolean类型
delete(key):根据key删除一个键值对,返回Boolean类型
补充:ES6中还有几个重要的知识点,这几个知识点我准备单独准备再写几个文章(TODO)在写中。。。
ES7(2016)
12. Array Includes
- 在ES7之前,如果我们想判断一个数组中是否包含某个元素,需要通过 indexOf 获取结果,并且判断是否为 -1。
- 在ES7中,我们可以通过includes来判断一个数组中是否包含一个指定的元素,根据情况,如果包含则返回 true, 否则返回false
const arr = [ 'js', 'html', 'css' ]
console.log(arr.includes('js')) // true
console.log(arr.includes('vue')) // false
console.log(arr.includes('html', 2)) // false 第二个参接受的是索引,表示从哪个索引位置开始判断
13. 指数(乘方) exponentiation运算符
const result1 = Math.pow(4, 4)
// ES7: **
const result2 = 4 ** 4
console.log(result1, result2) // 256 256
ES8(2017)
14. Objece.values
- 之前我们可以通过 Object.keys 获取一个对象所有的key,在ES8中提供了 Object.values 来获取所有的value值
const obj = {
name: '小方',
age: 18,
height: 1.88
}
const values = Object.values(obj)
console.log(values) // [ '小方', 18, 1.88 ]
15. Object entries
- 通过Object.entries 可以获取到一个数组,数组中会存放可枚举属性的键值对数组
const obj = {
name: '小方',
age: 18,
height: 1.88
}
console.log(Object.entries(obj)) // [ [ 'name', '小方' ], [ 'age', 18 ], [ 'height', 1.88 ] ]
for(const [key, value] of Object.entries(obj)){
console.log(key, value)
// name 小方
// age 18
// height 1.88
}
// 如果是一个数组
console.log(Object.entries(['js', 'html', 'css'])) // [ [ '0', 'js' ], [ '1', 'html' ], [ '2', 'css' ] ]
// 如果是一个字符串
console.log(Object.entries('js')) // [ [ '0', 'j' ], [ '1', 's' ] ]
16. String Padding
- 某些字符串我们需要对其进行前后的填充,来实现某种格式化效果,ES8中增加了 padStart 和 padEnd 方法,分别是对字符串的首尾进行填充的
const message = 'hello world'
console.log(message.padStart(15, 'a')) // aaaahello world 第一个参数就是总长(length)
console.log(message.padEnd(15, 'b')) // hello worldbbbb
// 应用场景 身份证脱敏
const idCard = '342866199909159899'
const firstNum = idCard.slice(-4)
console.log(firstNum.padStart(idCard.length, '*')) // **************9899
17.Trailing Commas
- 在ES8中,我们允许在函数定义和调用时多加一个逗号,个人觉得对我们平时开发没啥用
function foo(n, m, ){
console.log(n, m)
}
foo(10, 20)
18. Object Descriptors
- ES8中增加了另一个对对象的操作是 Object.getOwnPropertyDescriptors、Object.getOwnPropertyDescriptor
var obj = {
_age: 18,
_eating: function() {}
}
Object.defineProperties(obj, {
name: {
configurable: true,
enumerable: true,
writable: true,
value: "fang"
},
age: {
configurable: true,
enumerable: true,
get: function() {
return this._age
},
set: function(value) {
this._age = value
}
}
})
// 获取某一个特性属性的属性描述符
console.log(Object.getOwnPropertyDescriptor(obj, "name"))
// { value: 'fang', writable: true, enumerable: true, configurable: true }
console.log(Object.getOwnPropertyDescriptor(obj, "age"))
// {
// get: [Function: get],
// set: [Function: set],
// enumerable: true,
// configurable: true
// }
// 获取对象的所有属性描述符
console.log(Object.getOwnPropertyDescriptors(obj))
// {
// _age: { value: 18, writable: true, enumerable: true, configurable: true },
// _eating: {
// value: [Function: _eating],
// writable: true,
// enumerable: true,
// configurable: true
// },
// name: {
// value: 'fang',
// writable: true,
// enumerable: true,
// configurable: true
// },
// age: {
// get: [Function: get],
// set: [Function: set],
// enumerable: true,
// configurable: true
// }
// }
ES9(2018)
Object spread operators:对象展开运算,前面有
Promise finally 这个会在promise单独写
ES10
19.flat flatMap
- flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回
const arr = [[1, 2], [3, [4]], [5], [6, [7,8, [9]]]]
// console.log(arr.flat()) // 默认是一级 [ 1, 2, 3, [ 4 ], 5, 6, [ 7, 8, [ 9 ] ] ]
console.log(arr.flat(Infinity)) // 如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数 [1, 2, 3, 4, 5, 6, 7, 8, 9 ]
// flatMap的应用场景
const messages = ["Hello World", "my name is fang"]
const words = messages.flatMap(item => {
return item.split(" ")
})
console.log(words) // [ 'Hello', 'World', 'my', 'name', 'is', 'fang' ]
20. Object fromEntries
- ,我们可以通过 Object.entries 将一个对象转换成 entries,那么如果我们有一个entries了,如何将其转换成对象呢?ES10提供了 Object.formEntries来完成转换
const obj = {
name: '小方',
age: 18,
height: 1.88
}
const entries = Object.entries(obj)
console.log(entries) // [ [ 'name', '小方' ], [ 'age', 18 ], [ 'height', 1.88 ] ]
const info = Object.fromEntries(entries)
console.log(info) // { name: '小方', age: 18, height: 1.88 }
// 应用场景: 解析我们url后面携带的参数
const url = 'name=fang&age=18&height=1.88'
const params = new URLSearchParams(url)
const paramsObj = Object.fromEntries(params)
console.log(paramsObj) // { name: 'fang', age: '18', height: '1.88' }
21. trimStart trimEnd
- 去除一个字符串首尾的空格,我们可以通过trim方法,如果单独去除前面或者后面呢? pES10中给我们提供了trimStart和trimEnd
const message = ' hello world '
console.log(message.trimStart())
console.log(message.trimEnd())
22. Symbol description
- 获取Symbol的属性
const a = Symbol('aaa')
console.log(a.description) // aaa
ES11
23. BigInt
- 在早期的JavaScript中,我们不能正确的表示过大的数字
- 那么ES11中,引入了新的数据类型BigInt,用于表示大的整数
- BitInt的表示方法是在数值的后面加上n
const bigInt = 900719925474099100n
console.log(bigInt + 10n)
const num = 100
console.log(bigInt + BigInt(num))
const smallNum = Number(bigInt)
console.log(smallNum)
24. Nullish Coalescing Operator(空值合并操作符)
const foo = undefined
// const bar = foo || "default value"
const bar = foo ?? "default value"
console.log(bar) // default value
25. Optional Chaining(可选链)
const info = {
name: "fang",
// friend: {
// girlFriend: {
// name: "test"
// }
// }
}
// console.log(info.friend.girlFriend.name) // Cannot read properties of undefined (reading 'girlFriend')
console.log(info.friend?.girlFriend?.name) // test || undefined
26.Global This
- 在之前我们希望获取JavaScript环境的全局对象,不同的环境获取的方式是不一样的
- 比如在浏览器中可以通过this、window来获取
- 比如在Node中我们需要通过global来获取
- 那么在ES11中对获取全局对象进行了统一的规范:globalThis
console.log(globalThis)
console.log(this) // 浏览器下
console.log(global) // node下
27. for..in标准化
// for...in 标准化: ECMA
const obj = {
name: "小方",
age: 18
}
for (const item in obj) {
console.log(item)
}
这些单独写文章
ES12
28. FinalizationRegistry
- FinalizationRegistry 对象可以让你在对象被垃圾回收时请求一个回调
- 通过调用register方法,注册任何你想要清理回调的对象,传入该对象和所含的值
const finalRegistry = new FinalizationRegistry((value) => {
console.log("注册在finalRegistry的对象, 某一个被销毁", value)
})
let obj = { name: "小方" }
let info = { age: 18 }
finalRegistry.register(obj, "obj")
finalRegistry.register(info, "value")
obj = null
info = null
29. WeakRefs
- 如果我们默认将一个对象赋值给另外一个引用,那么这个引用是一个强引用
- 如果我们希望是一个弱引用的话,可以使用WeakRef;
let obj = { name: "why" }
let info = new WeakRef(obj)
30. logical assignment operators(逻辑分配运算符)
// 1.||= 逻辑或赋值运算
let message = null
message ||= 'default value'
console.log(message) // default value
// 2.&&= 逻辑与赋值运算
let info = {
name: "fang"
}
info &&= info.name
console.log(info) // fang
// 3.??= 逻辑空赋值运算
let message2 = 0
message2 ??= "default value"
console.log(message2) // 0
31. replaceAll(字符串替换)
const p = 'hello world and world';
console.log(p.replace('world', 'fang')) // hello fang and world
console.log(p.replaceAll('world', 'fang')) // hello fang and fang
以上就是ES6至ES12比较常见的知识点和常见用法。也欢迎大家补充,感谢~~~