学习笔记 JavaScript ES6 Proxy

学习内容:

  • 代理
  • 常用拦截方法

ES 5当中实现拦截的方法:

let obj = {}
let newValue = ''
Object.defineProperty(obj, 'name', {
    get() {
        return newValue
    },
    set(val) {
        console.log('set')
        newValue = val
    }
}) 
obj.name = 'test'
console.log(obj.name)

-------
set
test

ES6 Proxy

// 第一个参数是拦截或是要包装的对象或方法,
// 第二个参数是代理的配置,会对应一些钩子函数,
// 比如上面的get/set方法都可以称为钩子函数,
// 或者说在某些操作执行之前,要执行的函数称为钩子函数。
let obj = {}
let p = new Proxy(obj, {})
p.name = 'test'
console.log(obj.name);
for(let key in obj) {
    console.log(key);
}

----------
test
name
拦截器作用
get拦截对象属性的读取,比如proxy.name和proxy[name]
set拦截对象属性的设置,返回一个布尔值,比如proxy.name=v或proxy['name'] = v
has拦截propKey in proxy的操作,返回一个布尔值
ownKeys

拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、

for...in循环,返回一个数组

deleteProperty拦截delete proxy[propKey]的操作,返回一个布尔值
apply拦截函数的调用、call和apply操作
construct拦截new命令,返回一个对象

 

下面这个例子是对数组的代理,下标位置有值存在则返回对应的值,没有返回error:

let arr = [1, 2, 3]
arr = new Proxy(arr, {
    get(target, prop) {
        console.log(target, prop)
        return prop in target ? target[prop] : 'error'
    }
})

console.log(arr[1]);

---------------------
(3) [1, 2, 3] '1'
2

再来一个对象代理的例子:

let dict = {
    'Good' : '好',
    'morning' : '早上'
}

dict = new Proxy(dict, {
    get(target, prop) {
        return prop in target ? target[prop] : prop
    }
}) 

console.log(dict['Good'])
console.log(dict['haha']);

----------
Good
haha

拦截方式 : has()

let range = {
    start : 1,
    end : 5
}

range = new Proxy(range, {
    has(target, prop) {
        return prop >= target.start && prop <=target.end
    }
})

console.log(2 in range) 
console.log(10 in range)

--------
true
false

拦截方式:ownKeys 

对象的循环遍历时拦截

let userinfo = {
    username : 'Sure',
    age : 36,
    _password : '***'
}

userinfo = new Proxy(userinfo, {
    ownKeys(target) {
        return Object.keys(target).filter(key => !key.startsWith('_'))
    }
})

for(let key in userinfo) {
    console.log(key);
}

console.log(Object.keys(userinfo));
-----------
username
age
(2) ['username', 'age']

拦截方式deleteProperty() 

对象删除属性时拦截

let obj = {
    k : 'k',
    v : 'v',
    _p : '**'
}

obj = new Proxy(user, {
    deleteProperty(target, prop) {
        if(prop.startsWith('_') {
            throw new Error('不可删除')
        } else {
            delete target[prop]
            return true // 不要忘了返回boolean
        }
    }
})

拦截方式apply()

用于拦截函数、call、apply等

// 例子:对于参数不固定的求和
let sum = (...args) => {
    let num = 0
    args.forEach(item => {
        num += item
    })
    return num
}

sum = new Proxy(sum, {
    // 第一个参数,是被拦截对象,第二个参数是上下文,
    // 第三个参数是目标对象参数的数组
    apply(target, ctx, arg) {
        return target(...arg) * 2
    }
})
console.log(sum(1, 2));
console.log((sum.call(null, 1, 2, 3))) // 不需要改变this指向,所以第一个参数为null

//  apply后面的参数是数组
console.log(sum.apply(null, [1, 2, 3])) // 同样,不需要改变this指向,所以第一个参数为null

---------
6
12
12

 拦截方式construct()

用于拦截new()

let User = class {
    constructor(name) {
        this.name = name
    }
}
User = new Proxy(User, {

    // 这个拦截操作必需要返回一个对象
    construct(target, args, newTartget) {
        console.log('construct');
        return new target(...args)
    }
})

console.log(new User('test'));

--------------------
construct
User {name: 'test'}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值