ES6知识点合集由浅入深

写在前面的一些话,对于ES6之前一直都是用到哪里查哪里。一直也没有机会完全的读完阮一峰老师的书。刚好这段疫情时间有充足的时间用来学习,下面这篇文章可以带你了解es6新增属性、对象、数据结构等。如果真的有时间不妨读完阮一峰老师的书

let与块及作用域

es6以前只有全局作用域与函数作用域,es6中增加了块级作用域。

  • es6之前
if(true){
    var a = 1
    console.log(a) //1
}
console.log(a) //1
  • es6
if(true){
    let a = 1
    console.log(a) //1
}
console.log(a) //undefind
  • const

声明后不可以修改内存地址

const test = 1234
test = 1 //报错
const test = {}
test.name = 1 
console.log(test.name) //1
  • 编程规范
    • 不使用var
    • 默认使用const
    • 需要修改的变量通过let声明
数组解构

通过位置解构元素

  • 以前的数组取值
const arr = [100,200,300]
const firtst = arr[0]
const two = arr[1]
const three = arr[2]
  • 使用数组解构
const arr = [100,200,300]
const [firtst,two,three] = arr
console.log(firtst)//100
  • 解构需要的变量
const arr = [100,200,300]
const [ , ,three] = arr
console.log(three)//300
  • 解构当前成员后面的所有成员

只能在最后一个成员中使用

const arr = [100,200,300]
const [firtst, ...three] = arr
console.log(firtst) //100
console.log(three) //[200,300]
const arr = [100,200,300]
const [...firtst,three] = arr
console.log(firtst) //报错
  • 解构设置默认值
const arr = [100]
const [firtst, two=200] = arr
console.log(two) //200
  • 使用通过 ‘/’ 分割字符串,取第二个值
    • es6之前
        const str = 'foo/bar/baz'
        const tmp = str.split('/')
        const rootdir = tmp[1]
        console.log(rootdir)//bar
    
    • es6
        const str = 'foo/bar/baz'
        const [,rootdir] = str.split('/')
        console.log(rootdir)//bar
    
对象解构

通过变量名解构

const obj = { 
    name : 'abc',
    age : 18
}
const { name } = obj
console.log(name) //abc
const obj = { 
    name : 'abc',
    age : 18
}
const { ..._obj } = obj
console.log(_obj) //{ name: 'abc', age: 18 }

注意通过 ‘…’ 解构的对象中的引用类型为浅拷贝

const obj = { 
    name : 'abc',
    age : 18,
    tag : [
        'php','js'
    ]
}
const { ..._obj } = obj
obj.name = 'zxc'
obj.tag[0] = 'java'
console.log(_obj.name) //abc
console.log(_obj.tag[0]) //java

关于块级作用域 变量名占用可以使用别名处理

const obj = { 
    name : 'abc',
    age : 18
}
const name = 'zxc'
const { name } = obj //报错 Identifier 'name' has already been declared
const obj = { 
    name : 'abc',
    age : 18
}
const name = 'zxc'
const { name : _name } = obj
console.log(_name) // abc

设置默认值值

const obj = { 
    // name : 'abc',
    // age : 18
}
const name = 'zxc'
const { 
    name : _name = 456 ,
    age = 17
} = obj
console.log(_name) // 456
console.log(age) // 17
模板字符串
  • 新特性
    • 支持多行字符串
    • 通过差值表达式插入JavaScript语句
const name = 'abc'
const msg = `hi ${name}`
console.log(msg) // hi abc
const name = 'abc'
const msg = `hi ${1+2}`
console.log(msg) // hi 3
* 带标签的模板字符串
```js
const name = 'abc'
const job = 'php'
function tag(strings,name,job){
    console.log(strings) // [ '', ' job is', '' ]
    console.log(name,job) // abc php
    return strings[0] + name +strings[1]+job
}
const str = tag`${name} job is ${job}`
console.log(str)//abc job is php
字符串扩展方法
  • includes

是否包含传输参数

const err = 'Error: foo is not defined'
console.log(err.includes('foo')) // ture
  • startsWith

以传入参数开头

const err = 'Error: foo is not defined'
console.log(err.startsWith('Error')) // ture
  • endsWith

以传入参数结尾

const err = 'Error: foo is not defined'
console.log(err.endsWith('defined')) // ture
  • repeat

重复原字符串n次

const str = '123='
console.log(str.repeat(2)) //123=123=
参数默认值
  • 定义函数参数默认值
function foo (str='no'){
    console.log(str)
}
foo() // no
foo('yes') //yes

带有默认值的参数一定要放到最后

function foo (start,str='no'){
    console.log(start+str)
}
foo('=') // =no
foo('yes','no') //yesno
剩余参数获取
function test (name,...attributes){
    console.log(`${name} ${attributes.join('-')}`)
}
test('zzy','php','js','java') //zzy php-js-java
展开运算符
const arr = [1,2,3,4,5]
console.log(...arr) //1 2 3 4 5

对象展开从上到下的顺序,如果存在相同变量,后面的会替换前面的

const obj = {
    name:'zzy',
    age:18
}
const _obj={
    ...obj,
    job:'web',
    age:19
}
console.log(_obj) //{ name: 'zzy', age: 19, job: 'web' }
箭头函数 (箭头函数中的this指向的是父级的环境)

定义一个函数

const inc = n => n+1
console.log(inc(10)) //11

下方代码等于上方代码

const inc = (n)=>{
    return n+1
}
console.log(inc(10)) //11

返回数组中所有的偶数

const arr = [1,2,3,4,5,6]
const even_numbers=arr.filter(val=>val%2===0)
console.log(even_numbers)

箭头函数中的this 箭头函数不会改变this指向,在箭头函数的外面this 指向什么就是什么。一般函数的this只跟它的执行者有关,跟在哪定义和在哪执行无关,但是箭头函数就特殊了,它指向执行者的上下文,而不再是执行者了

const person = {
    name : 'Tom',
    say : function(){
        console.log(`hi my name is ${this.name}`)
    }
}
person.say() //hi my name is Tom
const person = {
    name : 'Tom',
    say :()=>{
        console.log(`hi my name is ${this.name}`)
    }
}
person.say() //hi my name is undefined

箭头函数实际应用 传统使用that or _this 的地方都可以使用箭头函数

const person = {
    name: 'Tom',
    say:function() {
        setTimeout(() => {
            console.log(`hi my name is ${this.name}`)
        }, 1000)
    }
}
person.say() //hi my name is Tom
对象字面量增强
const bar = '123'
const obj = {
    bar : bar ,
    say : function(){

    }
}
const bar = '123'
const obj = {
    bar,
    say (){

    }
}

动态key与计算属性

const obj = {
    [Math.random()]:'abc'
}
console.log(obj) //{ '0.4094474269217101': 'abc' }
Object.assign 对象合并

用后面的对象属性覆盖第一个对象 返回第一个对象, 此方法为浅拷贝如果对象中包含引用类型依然会改变

const obj_a={
    a:1,
}
const obj_b={
    b:1,
}
const target =  Object.assign(obj_a,obj_b)
console.log(target === obj_a) //true
console.log(target) // { a: 1, b: 1 }
Object.is 判断两个值是否相等

一般情况下不建议使用,而是使用 ‘’ or '=’

console.log(Object.is(1,1)) // true
console.log(Object.is(-0,0)) // false
console.log(Object.is(NaN,NaN)) //true
console.log(Object.is(null,null)) //true
console.log(Object.is(undefined,undefined)) //true
console.log(Object.is([1],[1])) //true
Proxy 代理器
const obj = { 
    name : 'abc',
    age : 18
}
const objProxy = new Proxy(obj,{
    get(target,property){
        console.log(target,property) 
        //{ name: 'abc', age: 18 } name
        return property in target ? target[property] : 'default'
    },
    set(target,property,value){
        console.log(target,property,value)
        // { name: 'abc', age: 18 } name 1
        target[property]=value
    }
})
console.log(objProxy.name) // abc
console.log(objProxy.job)  // default
objProxy.name=1
Proxy vs Object.defineProperty
  • Object.defineProperty

    • 对象读取
    • 对象写入
  • Proxy

    • 对象读取
    • 对象写入
    • 方法调用
    • 非入侵式
    • delete

    delete

    const obj = { 
        name : 'abc',
        age : 18
    }
    const objProxy = new Proxy(obj,{
        get(target,property){
            console.log(`get`)
            return property in target ? target[property] : 'default'
        },
        set(target,property,value){
            console.log(`set`)
            target[property]=value
        },
        deleteProperty(target,property){
            console.log(`delete`)
            delete target[property]
        }
    })
    
    objProxy['name'] // get
    objProxy['name']=123 // set
    delete objProxy['name'] // delete
    
  • Proxy 可以监听到的方法

handler触发方式
get读取某个属性
set写入某个属性
hasin操作符
deletePropertydelete操作符
getPropertypeOfObject.getPropertypeOf()
setPropertypeOfObject.setPropertypeOf()
isExtensibleObject.isExtensible()
preventExtensionsObject.preventExtensions()
getOwnPropertyDescripttorObject.getOwnPropertyDescripttor()
definePropertyObject.defineProperty()
ownKeysObject.getOwnPropertyNames() or Object.getOwnPropertySymbols()
apply调用一个函数
construct用new 调用一个函数

Proxy监听数组方法

const list = []
const listProxy = new Proxy(list,{
    set(target,property,value){
        console.log('set',target,property,value)
        target[property]=value
        return true
    }
})
listProxy.push(100)
listProxy.push(101)
Reflect.get()

Reflect 就是 Proxy 的默认实现,它提供了统一的一套操作对象的api

const obj = { 
name: 'abc',
    age: 18
}
const objProxy = new Proxy(obj, {
    get(target, property) {
        return Reflect.get(target, property)
    },
    set(target, property, value) {
        target[property] = value
        Reflect.set(target, property,value)
    },
    delete(target, property) {
        Reflect.delete(target, property)
        return true
    }
})
promise

解决了传统异步编程中回调函数嵌套过深的问题,后面会单独写相关部分

class类(关键字)

原型链实现

function Person (name){
    this.name = name
}
Person.prototype.say = function(){
    console.log(`My name is ${this.name}`)
}

const person = new Person('Tom')
person.say() //My name is Tom

es6class实现

class Person {
    constructor(name){
        this.name=name
    }
    say(){
        console.log(`My name is ${this.name}`)
    }
}
const person = new Person('Tom')
person.say() //My name is Tom

静态方法,this不会挂载到实例对象

class Person {
    constructor(name){
        this.name=name
    }
    say(){
        console.log(`My name is ${this.name}`)
    }
    static create (name){
        return new Person(name)
    }
}
const person = Person.create('Tom')
person.say() // My name is Tom

extent 类的继承

  • super()必须在this之前
class Person {
    constructor(name){
        this.name=name
    }
    say(){
        console.log(`My name is ${this.name}`)
    }
    static create (name){
        return new Person(name)
    }
}
class Student extends Person{
    constructor(name,number){
        super(name)
        this.number = number
    }
    hello(){
        super.say()
        // 等同于 this.say()
        console.log(`number is ${this.number}`)
    }
}

const student = new Student('Tom',123)
student.hello()
// My name is Tom
// number is 123
Set(集合)全新的数据结构
const s = new Set()
s.add(1).add(2).add(3).add(1)
console.log(s) // 1 2 3 
// 循环方式-自带的forEach方法
s.forEach(item=>console.log(item))
// 循环方式-es6 中的 for of 方法
for(let item of s){
    console.log(item)
}

// 长度
console.log(s.size)//3

// has 是否存在指定的值 返回 true false
console.log(s.has(1))

// delete 删除指定值 返回 true false
console.log(s.delete(3))
console.log(s) // 1 2 

Set 与 数组互转

const arr = [1,2,3,4]

// 数组转Set 
const s1 = new Set(arr)
console.log(s1) // Set(4) { 1, 2, 3, 4 }

//  Set 转数组
const a1 =  Array.from(s1)
console.log(a1) // [ 1, 2, 3, 4 ]

// 结构方式
console.log([...s1]) // [ 1, 2, 3, 4 ]

数组去重—Set

const arr = [1,1,2,3,4,1]
const arr2 = [...new Set(arr)]
console.log(arr2) //[ 1, 2, 3, 4 ]
Map (类似对象数据结构)全新的数据结构

严格意义上的键值对集合,用来映射两个任意类型数据的对应关系

const m = new Map()
const tom = { name:'tom' }
m.set(tom,90)
console.log(m) // Map(1) { { name: 'tom' } => 90 }
console.log(m.get(tom))//90
// m.has()
// m.delete()
// m.clear()

// 遍历
m.forEach((val,index)=>console.log(val,index)) // 90 { name: 'tom' }
Symbol 全新的数据结构
const s = Symbol()
console.log(s) // Symbol()
console.log(typeof s) //symbol

作为对象key

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

实现私有成员 为对象增加独一无二的属性标识符

const name = Symbol()
const person = {
    [name]:'Tom',
    say(){
        console.log(`name is ${this[name]}`)
    }
}
person.say() //name is Tom

Symbol唯一性

console.log(Symbol('foo')===Symbol('foo')) // false
// Symbol.for 活

Symbol.for 接收字符串参数。相同的字符串就会返回相同的Symbol

console.log(Symbol.for('foo')===Symbol.for('foo')) // true
console.log(Symbol.for('true')===Symbol.for(true)) // true

Symbol提供了一些内置的对象,这些对象可以实现一些js的接口

  • Symbol.iterator
  • Symbol.hasInstance

尝试改写obj.toString() 方法

let obj = {
    
}
console.log(obj.toString()) // [object Object]

let obj1 = {
    [Symbol.toStringTag]:'Tom',
    key:'value'
}
console.log(obj1.toString()) // [object Tom]

对象中的Symbol 获取

// Object or Array常用的遍历或者获取方法都无法获得Symbol
for(let k in obj1){
    console.log(k) // 只会输出 key
}
console.log(Object.keys(obj1)) // ['key']

// 如若需要获取可以使用 getOwnPropertySymbols只能获取 Symbol类型的属性名
console.log(Object.getOwnPropertySymbols(obj1)) //[ Symbol(Symbol.toStringTag) ]
for of 循环
// 数组遍历
const arr = [100, 200, 300] 
for(val of arr){
    console.log(val) //100 200 300
}

//Set遍历
const s = new Set(['foo','bar'])
for(val of s){
    console.log(val) //foo bar
}

//Map遍历
const m = new Map()
m.set('foo',1)
m.set('bar',2)
for([k,v] of m){
    console.log(k,v) //foo 1   bar 2
}

// 对象遍历 无法变量
const obj = {
    a:1,
    b:2
}
//TypeError: obj is not iterable
for(let val of obj){
    console.log(val)
}

iterator 可迭代接口

const s = new Set([1,2,3])
const iterator = s[Symbol.iterator]()
console.log(iterator.next()) // { value: 1, done: false }
console.log(iterator.next()) // { value: 2, done: false }
console.log(iterator.next()) // { value: 3, done: false }
console.log(iterator.next()) // { value: undefined, done: true }

实现可迭代接口

  • 伪代码
    const obj = {
        // 实现可迭代接口 iterable
        [Symbol.iterator](){
            return {
                // 实现迭代器接口  iterator
                next(){
                    // 实现了迭代结果接口 iterationResult
                    return{
                        val:'aa',
                        done:true
                    }
                }
            }
        }
    }
    

实现for of 遍历对象

const obj = {
    a: 1,
    b: 2,
    // 实现可迭代接口 iterable
    [Symbol.iterator]() {
        let index = 0
        const keys = Object.keys(this)
        return {
            // 实现迭代器接口  iterator
            next: () => {
                // 实现了迭代结果接口 iterationResult
                const key = keys[index]
                const result = {
                    value: [this[key],key],
                    done: index >= keys.length
                }
                index++
                return result
            }
        }
    }
}
for (let [val,key] of obj) {
    console.log('循环体',val,key)
    // 循环体 1 a
    // 循环体 2 b
}

设计模式—迭代器模式

  • 传统实现
    const todo = {
        life : [ '吃饭', '睡觉', '打豆豆' ],
        learn : [ '语文', '数学', '外语' ],
        // 传统遍历
        each:function(callbacl){
            for(const item of [...this.life,...this.learn]){
                callbacl(item)
            }
        }
    }
    todo.each(val=>console.log(val)) //会遍历每一个属性
    
  • iterator 实现
        const todo = {
            life: ['吃饭', '睡觉', '打豆豆'],
            learn: ['语文', '数学', '外语'],
            [Symbol.iterator](){
                const all = [...this.life,...this.learn]
                let index = 0
                return {
                    next(){
                        return {
                            value : all[index],
                            done : index++ >= all.length
                        }
                    }
                }
            }
        }
        for(let item of todo){
            console.log(item) // 吃饭 睡觉 打豆豆 ...
        }
    
Generator 生成器函数
  • 特点
    • 自动返回 iterable
    • 惰性执行 需调用next()
  • 减少异步编程嵌套

基本语法

 function * foo(){
     console.log('100')
     yield 100
     console.log('200')
     yield 200
     console.log('300')
     yield 300
 }
 const res = foo()
 console.log(res) // Object [Generator] {}
 console.log(res.next()) // 100  { value: 100, done: false }
 console.log(res.next()) // 200  { value: 200, done: false }
 console.log(res.next()) // 300  { value: 300, done: true }

Generator应用–发号器

function * careteIdMaker(){
    let id = 1
    while(true){
         yield id++
    }
}
const idMaker = careteIdMaker()
console.log(idMaker.next().value) // 1
console.log(idMaker.next().value) // 2
console.log(idMaker.next().value) // 3

Generator应用–实现iterator接口

const todo = {
    life: ['吃饭', '睡觉', '打豆豆'],
    learn: ['语文', '数学', '外语'],
    [Symbol.iterator]:function * (){
        const all = [...this.life,...this.learn]
        for(const item of all){
            yield item
        }
    }
}
for(let item of todo){
    console.log(item) // 吃饭 睡觉 打豆豆 ...
}
ECMA 2016
  • 数组 includes
const arr = [ 'foo', 1, NaN, false] 
console.log(arr.includes('foo')) //true
console.log(arr.includes(1))     //true
console.log(arr.includes(NaN))   //true
console.log(arr.includes(false)) //true
  • 指数运算符
console.log(Math.pow(2,10)) // 1024
console.log(2 ** 10) // 1024
ECMA 2017
  • Object.values
const obj = {
    a:1,
    b:2
}

console.log(Object.values(obj)) // [ 1, 2 ]
  • Object.entries
const obj = {
    a:1,
    b:2
}
console.log(Object.entries(obj)) // [ [ 'a', 1 ], [ 'b', 2 ] ]

通过for of 遍历对象

const obj = {
    a:1,
    b:2
}
for(const [ key, value ] of Object.entries(obj)){
    console.log(key,value) 
    // a 1 
    // b 2
}

Object对象转Map对象

const obj = {
    a:1,
    b:2
}
console.log(new Map(Object.entries(obj))) // Map(2) { 'a' => 1, 'b' => 2 }
  • Object.getOwnPropertyDescriptors (获取对象中属性的完整描述信息)
const p1 = {
    firstName : 'Zhao',
    lastName : 'Zhong',
    get fullName(){
        return `${ this.firstName }-${this.lastName}`
    }
}
console.log(p1.fullName) // Zhao-Zhong

const p2 = Object.assign({},p1)
p2.firstName = 'zzy'
console.log(p2.fullName) // Zhao-Zhong

const p3 = Object.defineProperties({},Object.getOwnPropertyDescriptors(p1))
p3.firstName = 'wzz'
console.log(p3.fullName) // wzz-Zhong
  • padStart、padEnd字符串填充方法
const obj = {
    html : 5,
    css : 16,
    javascript : 128
}
for(const [name,count] of Object.entries(obj)){
    console.log(name,count)
}
//html 5
//css 16
//javascript 128 

for(const [name,count] of Object.entries(obj)){
    console.log(`${name.padEnd(16,'-')}|${count.toString().padStart(3,'0')}`)
}
// html------------|005
// css-------------|016
// javascript------|128
  • 允许函数参数中添加伪逗号
  • Async/Await
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵忠洋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值