塞壬的欢歌

导航

ES6 学习笔记 4 完结 --- Reflect, Proxy, Generator, Iterator

ES6(2015)

反射 Reflect

调用方法 .apply()

// ES5
Math.floor.apply(null,[3.7])  // 3

// ES6
Reflect.apply(Math.floor,null,[3.7]) 

作用: 可以将方法当做参数,根据实际情况变化方法名

// ES5 
let price = 91.5
if(price > 100){
	price = Math.floor.apply(null,[price])
}else {
	price = Math.ceil.apply(null,[price])
}
// ES6
Reflect.apply(price >100 ? Math.floor : Math.ceil,null,[price])

实例化类 .construct()

实例化对象 .construct()

// ES5
let d = new Date()
// ES6
let d = Reflect.construct(Date,[])  // 无参使用 空数组

实例对象的方法 .defineProperty() & .deleteProperty()

// 定义属性
const student = {}
const o = Object.defineProperty(student,'name',{value:'Mike'}) // {name: 'Mike'}
const r = Reflect.defineProperty(student,'name',{value:'Mike2'}) // true
// 删除属性
const obj = {x:1,y:2}
const o = Object.deleteProperty(obj,'x') // {y:2}
const r = Reflect.deleteProperty(obj,'x') // true
// 查看属性
const obj = {x:1,y:2}
const o = obj.x  // 1
const r = Reflect.get(obj,'x')  // 1
// 查看属性描述符
const r = Reflect.getOwnPropertyDescriptor(obj,'x') // writable
// 查看原型对象
const ge = Reflect.getPropertyOf(obj)
// 查看属性是否存在
const r = Reflect.has(obj,'x')  // Reflect 特有
// 可扩展
const r = Reflect.isExtensible(obj) 
// 冻结扩展性
const z = Object.freeze(obj)
const r = Relfect.preventExtensions(obj)
// 查看属性名
const r = Reflect.ownKeys(obj)
// set
Reflect.set(obj,'z',4)
// 修改原型对象
Reflect.setPrototypeOf(obj,String.prototype) // 将对象变成了 string

代理 Proxy

中介,保护原始信息 ,代替 Object.defineProperty()

let o = {
    name : 'xm',
    price: 190
}
window.addEventListener('error',(e)=>{
    console.log(e.message)
    report('./') // 统一监控的方法
},true)

validator = function (target,key,value){
    if(Reflect.has(key)){
        if(key === 'price'){
            if(value >300){
                throw new TypeError('price exceed 300')
            }
        }
        target[key] = value
    }else {
        return false // 阻止写操作,只读
    }
}
let d = new Proxy(0,{
    get(target,key){
        if(key === 'price'){
            return target[key] + 20
        }else {
            return target[key] || ''
        }
    },
    set:validator
})
console.log(d.price) // 210 经过代理改变了

let r = Proxy.revocable(o,{ // 可撤销代理
    get(target,key){
        if(key === 'price'){
            return target[key] + 20
        }else {
            return target[key] || ''
        }
    }
})
let p = r.proxy.price // 相当于 d.price 
console.log(p) // 读取了数值
setTimeout(()=>{
    d.revoke() // 代理销毁
},1000)

作用:

  1. 保护原始信息,获取信息时,可以调整信息
  2. 阻止信息的修改
  3. 做校验,修改信息时,对超过值域的值进行阻断
  4. 监控,触发校验者的信息

发生器 Generator

暂停循环

function * loop (){
	for (let i = 0 ; i < 3; i ++ ){
		yield console.log(i)
	}
}
const l = loop() // 此时一次值也没有
l.next() // 0
l.next() // 1
l.next() // 2
l.next() // 没了 
// 每次 遇到 yield 就停 
// 依靠next() 来执行每一次的循环

语法

用* 定义的方法, 每次遇到 yield 就会停止 等待指令, 直到 .next(val) 执行 ,会跳过一个yield ,并给 yield赋值,影响yield等号左侧的值.

function * gen(){
    try {
        let val
        val = yield 1
        console.log(val)
    } catch (e){
        console.log(e.message)
    }
}

const l = gen()
const n1 = l.next() // 1  n1: {undefined,false}
const t1 = l.throw(new Error('ss')) // 使yield 异常
const r1 = l.return() // 提前结束
const n2 = l.next() // undefined  n2: {undefined,true}

遍历器 Iterator

不可遍历对象

let a = {
    b :{
        c: [1,2,3,4,5],
        d: [11,22,33,44,55,66],
        e: [111,222,333,444]
    },
    kk:{},
    zz:{}
}
// 将 c,d,e 中的数组 统一成一个数组 
// 常规做法 耦合度不够
let r = []
for(let [k,v] of Object.entries(a.b)){
    r = r.concat(v)
}
console.log(r) // 变成了新的数组

使用固定格式 给对象增加遍历器

// 理想做法
let r = []
for (let v of a ){
    r.push(v)
}
// 于是 , 需要增加遍历器接口
// 入口this固定格式 可迭代协议
a[Symbal.iterator] = function(){
    // 逻辑
    let a = this.a
    let keys = Reflect.ownKeys(a)
    let values = []
    // 出口固定格式 迭代器协议
    return {
        next(){
            if(!value.length){
                if(keys.length){
                   values = a[keys][0]   
                   keys.shift()
                }
            }
            done:!value.length,
            value:values.shift()
        }
    }
}

使用Generator 给对象增加遍历器

// 上步可见,迭代器协议的格式 和 Generator 的 返回值格式 完全一样.其实,Generator 就是一个迭代器协议.
a[Symbol.iterator] = function * (){
    let a = this.a
    let keys = Reflet.ownKeys(a)
    let values = []
    while(1){
        if(!values.length){
            if(keys.length){
                values = a[keys[0]]
                keys.shift()
                yield valuse.shift()
            }else {
                return false
            }
        }else {
            yield values.shift()
        }
    }
}

posted on 2020-04-07 20:56  塞壬无欢歌  阅读(147)  评论(0编辑  收藏  举报