0
点赞
收藏
分享

微信扫一扫

ECMAScript新特性

流计算Alink 2022-02-27 阅读 33

准备

依赖 nodemon 小工具

作用修改完代码自动执行

命令行代码:

  • code a.js 在当前目录下创建一个a.js的文件

  • del a.js 删除当前目录下的a.js文件

  • npx nodemon ./a.js 使用项目中的nodemon执行a.js文件

let 与块级作用域

let 声明的变量

  • 只在块作用域中生效
  • 没有声明提升
  • 存在暂时性死去

const关键字

  • 声明一个常量,不能修改(不能重新指向一个新的内存地址)
  • 其它和let一样

数组解构

const arr = [100,200,300]
// const [foo,bar,baz] = arr
// 取出特定的值
// const [,,baz] = arr
// console.log(baz) // 300
// 三点运算
// const [foo,...rest] = arr
// console.log(rest) // [ 200, 300, 400 ]
// arr长度小于赋值项数 多出来的项被赋值为undefined
// const [foo,bar,baz,more] = arr
// console.log(foo,bar,baz,more) // 100 200 300 undefined
// 设置默认值
const [foo,bar,baz,more=400] = arr
console.log(foo,bar,baz,more) // 100 200 300 400

对象的结构

  • 根据属性名去提取

  • 其他和数组一样

// const obj = {name:'zce' ,age:18}
const obj = {name1 : 'zce',age:18}
// const {name} = obj
// 重命名
const name = 'tom'
// const { name } = obj // SyntaxError: Identifier 'name' has already been declared
// const {name : objName} = obj
//console.log(name,objName) // tom zce
/*
重命名加设置默认值
*/
const {name:objName='jack'} = obj
/*结构console*/
const {log} = console

模板字符串

  • 支持换行
  • 插值表达式

带标签的模板字符串

const name = 'tom'
const gender = true
function myTagFunc(string ,name,gender){
    console.log(string,name,gender) //
    return '123'
}
const result = myTagFunc`hey,${name} is a ${gender}` // [ 'hey,', ' is a ', '' ] tom true
console.log(result) // '123'

字符串扩展方法

一下三个方法可以用来判断,字符串中是否包含指定的内容

  • includes()判断一个字符串是否包含指定的内容
  • startsWith()判断一个字符串是否已指定的内容开头
  • endsWith() 判断一个字符串是否已指定的内容结束

函数默认值的设置

  • 注意多个参数时,有默认值的参数,一定要放在后面
  • 用结构赋值,想咋传就咋传
// 短路运算的方式设置默认值
function foo1(enable){
    enable = enable || true
    consol.elog('foo invoked-enable')
    console.log(enable)
}
// 问题传入false也会使用默认值
foo1(false)
// 判断undefined,不传参数是参数会是undefined
function foo2(enable){
    enable = enable=== undefined?true:enable
    console.log('foo invoked - enable')
    console.log(enable)
}
// 有点麻烦
foo2()
// es6后可直接设置
function foo3(bar,enable=true){
    console.log('foo invoked - enable')
    console.log(enable)
}
// 没有传递实参,或者实参传递的是一个undefined是去使用
foo3()

剩余操作符

function foo(...args){console.log(args)}
foo('a','b','c','d') // ['a','b','c','d']


箭头函数

  • 箭头函数的this指向

对象字面量增强

  • 变量名与属性名一样只写变量名
  • 方法可以直接定义(普通的function)
  • 可以使用表达式的返回值作为属性名(计算属性名)
// 计算属性名
const obj={
    [Math.random()]:123
}

对象扩展方法

  • Object.assign() 将对各源对象中的属性复制到一个目标对象中
  • Object.is() 不常用
// Object.assign()
const surcel = {
    a:123,
    c:456
}
const target = {
    a:789,
    c:901
}
const result = Object.assign(target,sourcel)
console.log(target)
console.log(result===target) // true

Proxy

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

const personProxy = new Proxy(person,{
    // target代理对象(person)
    // property 访问的属性名
    get(target,property){
        console.log(target,property)
        return target[property]
    },
    // value 写入的属性值
    set(target,property,value){
    	console.log(target,property,value)
        target[property] =value
	},
    // 监听del操作
    deleteProperty(target,property){
        console.log(target,property)
        delete target[property]
    },
    // in操作符
    has(){
        
    },
    // Object.getPrototypeOf()
    getPrototypeOf(){},
    // Object.setPrototypeOf()
    setPrototypeOf(){},
    // Object.isExtensible()
    isExtensible(){},
    // Object.preventExtensione()
    PreventExtensions(){},
    // Object.getOwnPropertyDescriptor()
    getOwnPropertyDescriptor(){},
    // Object.defineProperty()
    defineProperty(){},
    //Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()
    ownKeys(){},
    // 调用一个函数
    apply(){},
    // 用new调用一个函数
    construct(){}
})

相比与Object.defineProperty()的优势

  • proxy更为强大

    • defineProperty只能监视属性的读写
    • proxy能够监视到更多的对象操作 (del操作,对象方法的调用)
  • 数组对象的监视 以往重写数组调用的方法

  • 以非侵入的方式监管对象的读写,即对已生成的对象不需要在进行任何的操作

// 数组对象的监视
const list = []
const listProxy = new Proxy(list,{
    set(target,property,value){
        // target 代理的数组
        // 数组的下标
        // 接收到的值
        console.log(target,property,value)
        return true // 设置成功
    }
    // 其它类似
})

Reflect

  • 静态类 不能通过new Reflect()获取对象,只能调用一些静态方法
  • 封装了一系列对对象的底层操作(14个静态方法别废弃了一个)
  • Reflect成员方法就是Proxy处理对象的默认实现
const obj = {
    foo:123,
    bar:456
}

const proxy = new Proxy(obj,{
    get(target,property){
        return Reflect.get(target,property)
    }
})

// console.log('name' in obj)
// console.log(delete obj['age'])
// console.log(Object.keys(obj))
console.log(Reflect.has(obj,'name'))
console.log(Reflect.deleteProperty(obj,'age'))
console.log(Reflect.ownKeys(obj))

Promise

  • 一种更优的异步编程解决方案
  • 解决了回调函数嵌套过深的问题

class类

// class 关键词
// 以往 构造函数
function Person(name){
    this.name = name
}
Person.prototype.say = function(){
    console.log(`hi,my name is ${this.name}`)
}

// 现在

class PersonClass{
    // 构造函数
    constructor(name){
        this.name = name
    }
    say(){
        console.log(`hi,my name is ${this.name}`)
    }
    // 静态方法
    static create(name){
        // 此处的this指向当前的类型
        return new Person(name)
    }
}
// 静态方法
// 以往
Person.create(name){
    return new Person(name)
}
// 现在使用static关键值


继承

// 以往用原型的方式实现继承
// 现在使用extends关键字
class Student extends Person{
    constructor(name,number){
        // super始终指向父类,调用它就是调用父类的构造函数
        super(name)
    }
    hello(){
        super.say()
        console.log(`my school number is ${this.number}`)
    }
}

Set数据结果

  • 与数组类似,但成员不能重复
const s = new Set()
s.add(1).add(2).add(3).add(4).add(2)
console.log(s)

s.forEach(i => console.log(i))
// for-of es6新增
for(let i of s){
    console.log(i)
}
// 与数组中的length同理
console.log(s.size)
// 判断集合中是否包含指定的值
console.log(s.has(100))
// 删除指定的值,删除成功返回true
console.log(s.delete(3))
// clear 清除集合中的全部内容
s.clear()
console.log(s)

// 数组去重
const arr = [1,2,3,4,5,6,1,2]
// const result = Array.from(new Set(arr))
const result = [...new Set(arr)]
console.log(result)

Map数据结构

  • 与对象类似
  • 对象结构中的键只能够是字符串类型,其它数据类型的键会调用toString()
  • Map可以用来映射两个任意类型数据的对应关系
const m = new Map()
const tom = {name:'tom'}
// 存数据
m.set(tom,90)
// 获取数据
m.get(tom)
// 判断数据
m.has()
m.delete()
m.clear()

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

Symbol

  • 对象的键都是string,可能产生冲突
  • Symbol 符号 表示一个独一无二得值
  • 最主要的作用是为对象添加一个独一无二的属性标识符
// cache缓存
// a.js
const cache = {}
cache['foo'] = Math.random()
// b.js
cache['foo'] = '123'

// Symbol()
console.log(Symbol('ber')==Symbol('ber')) // false
// 对象的类型可以是Symbol
// 私有成员
const Obj = Symbol()
const person = {
    [name]:'zce',
    say(){
        console.log(this[name])
    }
}
// Symbol.for() 维护了一个全局的注册表,为string和Symbol提供了一个一一对应的关系
// 会对不是String的参数调用toString()
const s1 = Symbol.for('foo')
const s2 = Symbol.for('foo')
console.log(s1===s2) true
// 自定义toString标签
const obj = {
    // Symbol.toStringTag 内置Symbol常量
    [Symbol.toStringTag]:'XObject'
    name:'sss'
}
console.log(obj.toString())
// 获取对象Symbol类型的键名
// keys只能获取到string类型的键名
console.log(Object.getOwnPropertySymbols(obj))

未来会新增一个BigInt的原始数据类型,用于存放根长的数值

循环

  • for 遍历数组
  • for …in… 遍历键值对
  • es6 for…of… 遍历所有数据 伪数组也可以 arguments dom节点的列表 set map
  • Map对象的遍历 会获取到一个数组 item 为键和值
  • obj 不可以遍历 需要使用特殊方法
// for of
const arr = [100,200,300,400]
for(const item of arr){
    console.log(item)
    // break 可以终止循环
    if(item > 100) break
}
// arr.forEach() // 不能终止遍历
// arr.some(()=>true) arr.every(()=>false) 终止遍历
// map遍历
for(const [key,value] of m){
    console.log(key,value)
}
// obj 的遍历 不能直接遍历




iterable接口 迭代器

  • 可迭代接口(iterable接口)就是for…of的前提,就是一种可以被for of 统一遍历访问的规格标准
  • 一个数据结构只要实现了iterable接口都可以使用for of
// 获取可迭代对象的迭代器
const set = new Set(['foo','bar','baz '])
const iterator = set[Symbol.iterator]()
iterator.next()

实现可迭代对象

// const obj={
//     [Symbol.iterator]:function(){
//         return {
//             next:function(){
//                 return {
//                     value:'zce',
//                     done:true
//                 }
//             }
//         }
//     }
// }


const obj={
    store:['foo','bar','baz'],
    [Symbol.iterator]:function(){
        let index = 0
        const self = this
        return {
            next:function(){
                const result = {
                    value:self.store[index],
                    done:index>=self.store.length
                }
                index++
                return result
            }
        }
    }
}

迭代器模式

const todos = {
    life:['吃饭','睡觉','打豆豆'],
    learn:['语文','数学','外语'],
    work:['喝茶'],
    
    each:function(callback){
        const all = [].concat(this.life,this.learn,this.work)
        for(const item of all){
            callback(item)
        }
    },
    [Symbol.iterator]:function(){
        const all = [...this.life,...this.learn,...this.work]
        let index = 0
        return {
            next :function(){
                return {
                    value : all[index],
                    done : index++ >=all.length
                }
            }
        }
    }
}
todos.each(function(item){
    console.log(item)
})
console.log('----------------')
for(const item of todos){
    console.log(item)
}

生成器(Generator)

  • 避免异步代码嵌套太深
  • 提供更好的异步编程解决方案
// 语法 调用生成器函数会返回一个生成器对象
function *foo(){
    console.log('zce')
    return 100
}
// 返回生成其对象
const result = foo()
// 生成器对象也实现了iterator接口(迭代器接口)
console.log(result.next())

/*
 yield 关键词
 调用next()方法 代码执行到yield关键词处,之后等待再次调用next()
 并将yield关键词后的结果返回
 执行到最后一个yield关键词后再次调用next(),会返回undefined,并将done的值置为true
*/

function * foo1(){
    console.log('111')
    yield 100
    console.log('222')
    yield 200
    console.log('333')
    yield 300
}
const generator = foo()
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())

生成器的应用场景

function *createIdMaker(){
    let id = 1
    while(true){
        yield id++
    }
}

const idMaker = createIdMaker()
console.log(idMaker.next().value)


const todos = {
    life:['吃饭','睡觉','打豆豆'],
    learn:['语文','数学','外语'],
    work:['喝茶'],
    [Symbol.iterator]:function*(){
        const all = [...this.life,...this.learn,...this.work]
        for(const item of all){
            yield item
        }
    }
}
for(const ite of todos){
    console.log(ite)
}

ES Modules

  • 语言化层面的模块化标准

ES 2016

  • 新增 includes 方法 数组中是否包含指定元素
// Array.prototype.includes
const arr = ['foo',1,NaN,false]
console.log(arr.indexOf(NaN))// false
console.log(arr.includes(NaN)) // true

// 指数运算符
// 2的10次方
// console.log(Math.pow(2,10))
console.log(2**10)

ECMAScript 2017

const obj = {
    foo:'value1',
    bar:'value2'
}
// 所有值的数组
console.log(Object.values(obj))
// 返回所有的键值对 二维数组
console.log(Object.entries(obj))
console.log(new Map(Object.entries(obj))) // obj转map
// 获取对象当中属性的完整描述信息
Object.getOwnPropertyDescriptors()
/* 
es5 后我们可以为对象定义get或set属性
get或set属性不能通过Object.assign()来复制
*/ 

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

const p2 = Object.assign({},p1)
p2.firstName = 'zce'
// 将fullName当成了一个普通的属性去复制了
console.log(p2) // { firstName: 'zce', lastName: 'Wang', fullName: 'lei Wang' }

const descriptors = Object.getOwnPropertyDescriptors(p1)
const p3 = Object.defineProperties({},descriptors)
p3.firstName = 'zce'
console.log(p3.fullName)



// 字符串填充方法
// String.prototype.padStart  String.prototype.padEnd
// 填充字符串的开始或结束位置,直到达到指定长度为止
const books = {
    html:5,
    css:16,
    javascript:128
}

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

// 可以在函数参数中添加尾逗号,调用和定义都可以
function(bar,baz,){
    
}

// Async Await promise的语法糖


举报

相关推荐

0 条评论