ECMAscript 2015 (ES6) 、ES7、ES8、 2020、2021笔记

209 阅读2分钟

ECMAscript

javascript 是 ECMAscript 的一种扩展语言 ECMAscript 提供了基础语言

浏览器环境: js = ECMAscript + BOM + DOM node环境: js = ECMAscript + fs + net + etc

对象结构赋值

const obj = {name: 'huahua', age: 19}
const name = 'jack'
const {name: reName = 'honghong', age} = obj

console.log(reName)

带标签的模板字符串

const a = '小明'
const b = '男'

const result = mtTag`hey, ${a} is a ${b}.`

function mtTag (strings, a, b) {
    return strings[0] + a + strings[1] + b + strings[2]
}

可以用来处理函数中的变量,更好的输出函数

字符串包含

include、 startsWith、endsWith

函数剩余参数

function (a, ...args) {}

注:args只能使用一次,并放在最后

展开数组

const arr = ['fpp', 'bar', 'bas']

console.log.apply(console, arr)
console.log(...arr)

对象字面量

const obj = {
    foo: 123,
    [1 + 2]: 123
}

可以通过【】中填写js 表达式,作为对象的属性名

判断对象是否相等

Object.is(JSON.stringify({}), '{}')

可以用来判断+0 -0,NaN 是否相等

Proxy

用于创建一个对象的代理,从而实现基本操作的拦截和自定义

const person = {
    name: 'xiaohua',
    age: 20
}

const personProxy = new Proxy(person, {
    get (target, property) { // 调取对应属性时
        return property in target ? target[property] : 'default'
    }
    set (target, property, value) {
        if (property === 'age') {
            if (!Number.isInterger(value)) {
                throw new TypeError(`${value} is no an int`)
            }
        }
        target[property] = value
    }
})

personProxy.age = 100

personProxy.gender = true

console.log(personProxy.name)
console.log(personProxy.xxx)

Reflect

对对象的操作

  1. Reflect.get(target, name, receiver)
  2. Reflect.set(target,name,value,receiver)
  3. Reflect.apply(target,thisArg,args)
  4. Reflect.construct(target,args[, newTarget])
  5. Reflect.defineProperty(target,name,desc)
  6. Reflect.deleteProperty(target,name)
  7. Reflect.has(target,name)
  8. Reflect.ownKeys(target)
  9. Reflect.preventExtensions(target)
  10. Reflect.isExtensible(target)
  11. Reflect.getOwnPropertyDescriptor(target, name)
  12. Reflect.getPrototypeOf(target)
  13. Reflect.setPrototypeOf(target, prototype)
const obj = {
    name: 'xiaohui',
    age: 18,
    sex: '男'
}

console.log(Reflect.has(obj, 'name'))
console.log(Reflect.deleteProperty(obj, 'age'))
console.log(Reflect.ownKeys(obj))

类的继承

class Person {
    constructor (name) {
        this.name = name
    }
    
    say() {
        console.log(`h1, my name is ${this.name}`)
    }
}

class Student {
    constructor (name, number) {
        super(name)
        this.number = number
    }
    
    hello () {
        super.say()
        console.log(`my school number is ${this.number}`)
    }
}

const s = new student('jack', '100')
s.hello()

MAP类型

可以使用任意数据类型作为对象的键。

const m = new Map()
const tom = {name: 'tom'}
m.set(tom, 90)
console.log(m)
console.log(m.get(tom))

// m.has
// m.delete
// m.get(tom)

m.forEach((value, key) => {
    console.log(value, key)
})

Symbol

主要避免对象,键的相同

const obj = {
    [Symbol()]: 123
}
console.log(obj)

// 可以通过Symbol.for 传入相同的字符串名称,得到相同的值
Symbol.for('foo') === Symbol.for('foo')   // TRUE
Symbol.for('true') === Symbol.for(true)   // TRUE

for .. of

 const s = new Set(['foo', 'bar'])
 for(const item of s) {
     console.log(item)
 }
 
 const m = new Map()
 m.set('foo', '123')
 m.set('bar', '345')
 
 for(const item of m) {
     console.log(item)   // ['foo', '123'] ['bar', '345']
 }
 // 可以使用解构语法
 for(const [key, value] of m) {
     console.log(key, value)   // 'foo', '123'    'bar', '345'
 }

迭代器

通过迭代器可以不用关心,数据内部结构,直接遍历即可

const obj = {
    name: ['张三', '李四', '王五'],
    age: [18, 23, 19],
    work: ['工人', '农民', '白领'],
    each: (callback) => {
        const all = [...this.name, ...this.age, ...this.work]
        all.forEach(item => {
            callback(item)
        })
    },
    [Symbol.iterator]: * () => {
        const all = [...this.name, ...this.age, ...this.work]
        for (const item of all) {
            yield item
        }
    }
}

// 外部即可通过 each方法, for.. of 调用,不必关心对象内部结构
for([key, value] of obj) {
    console.log(key, value)
}

ES7新增

// Array.prototype.includes--------------------------

const arr = ['foo', 1, NaN, false]
console.log(arr.includes('foo'))
console.log(arr.includes(NaN))  // 可以直接计算NaN是否存在

// 指数运算符(等价)-----------------------------------------
console.log(Math.pow(2, 10))
console.log(2 ** 10)

ES8新增

  • Object.value、Object.entires
  • Object.getOwnPropertyDescriptors(), 完整复制属性
  • String.padStart,String.padEnd // 可用于对齐字符串,排版
  • 函数允许添加 尾逗号
for(const [key, value] of Object.entires(obj)) {
    console.log(key, value)
}

const p1 = {
    firstName: 'lei',
    lastName: 'wang',
    get fullName() {
        retrun this.firstName + '' + this.lastName
    }
}

const descriptiors = Object.getOwnPropertyDescriptors(p1)
const p2 = Object.defineProperties({}, descriptiors) // 完整复制
p2.firstName = 'zce'
console.log(p2.fullName)

// 结果 'zce  wang' 


const books = {
    html: 5,
    css: 16,
    javascript: 128
}

for(const [name, count] of Object.entires(books)) {
    console.log(`${name.padEnd(16, '-')}|${count.toString().padStart(3, '0')}`)
}

// 结果: html-------------|005
//       css--------------|016
//       javascript-------|128

ECMAscript 2020、2021

?.(可选链操作符)的使用

在对象具有多层级属性时,以前都使用.来连接。如:

var a = {}
console.log(a.b)
//如果a不存在b属性,则输出undefined

但如果层级多余2个的情况。如上述判断a.b.c是否存在

var a = {}
console.log(a.b.c)
//则会报a.b undefined的错误。
//这种情况很常见,以前常用做法是用短路语法一层层过滤下去
a && a.b && a.b.c

现在有了?.可选链操作符后就方便多了。可直接写

a?.b?.c
//如果不存在a.b.c就会返回undefined,不会报错(写成a.b?.c不会报错,因为a.b返回undefined)

?? 的使用

是es2020新增的空位合并操作符:

a??b
//如果a为null或undefined,则返回b,否则返回a。与||的区别在于??只对null和undefined返回b,对于‘’ 0 false之类的返回a
null ?? 1   // 1
undefined ?? 1 //1
NaN ?? 1 //NaN
0 ?? 1 //0
'' ?? 1 // ''

null || 1 //1
undefined || 1 //1
NaN || 1  //1
0 || 1  //1
'' || 1 //1