proxy和reflect
ts
function delay(f, ms) {
return new Proxy(f, {
apply(target, thisArg, args) {
setTimeout(() => target.apply(thisArg, args), ms)
},
})
}
function sayHi(user) {
console.log(`Hello, ${user}!`)
}
sayHi = delay(sayHi, 3000)
console.log(sayHi.length) // 1 (*) proxy 转发“获取 length” 操作到目标对象
sayHi('John') // Hello, John! (3秒后)
function delay(f, ms) {
return new Proxy(f, {
apply(target, thisArg, args) {
setTimeout(() => target.apply(thisArg, args), ms)
},
})
}
function sayHi(user) {
console.log(`Hello, ${user}!`)
}
sayHi = delay(sayHi, 3000)
console.log(sayHi.length) // 1 (*) proxy 转发“获取 length” 操作到目标对象
sayHi('John') // Hello, John! (3秒后)
ts
function formatNumber(str) {
let lastStr = str.substring(str.indexOf('.'))
let formatStr = str.substring(0, str.indexOf('.'))
// ["0", "9", "8", "7", "6", "5", "4", "3", "2", "1"]
console.log(lastStr)
console.log(formatStr)
let re = formatStr.split('').reverse()
console.log(re)
return (
re.reduce((acc, cur, index) => {
return (index % 3 ? cur : cur + ',') + acc
}) + lastStr
)
}
console.log(formatNumber('1234569234280689.45'))
export {}
function formatNumber(str) {
let lastStr = str.substring(str.indexOf('.'))
let formatStr = str.substring(0, str.indexOf('.'))
// ["0", "9", "8", "7", "6", "5", "4", "3", "2", "1"]
console.log(lastStr)
console.log(formatStr)
let re = formatStr.split('').reverse()
console.log(re)
return (
re.reduce((acc, cur, index) => {
return (index % 3 ? cur : cur + ',') + acc
}) + lastStr
)
}
console.log(formatNumber('1234569234280689.45'))
export {}
ts
const dog = {
name: `小黄`,
friends: [
{
name: `小红`,
},
],
}
// 1.首先new一个Proxy对象
let proxy = new Proxy(dog, {
// 2.参数一为需要代理的数据,参数二为上图可以代理的13种的配置对象
get(target, property) {
// 3.参数1为上面dog对象,参数2为dog的属性
console.log(`get被监控到了`)
return target[property]
},
set(target, property, value, obj) {
// 4.参数1为上面dog对象,参数2为dog的属性,参数3为设置的新值
// 有点类似Object.defineProperty
console.log(obj)
console.log(target, property, value)
console.log(`set被监控到了`)
target[property] = value
},
})
// 那么接下来我们设置一下这个属性
// Dog.name = '小红' // set值时,发现不会打印 'set被监控到了'
// Dog.name // get值时,发现不会打印 'get被监控到了'
// 思考:为什么在set/get值的时候不会打印出来我们需要的东西呢?
// 上面说得很明白了,proxy相当于是一个壳,代理我们需要监控的数据,也就是我们要通过proxy来访问内部数据才会被监控到
proxy.name = `小红` // 打印输出 'set被监控到了'
console.log(proxy.name)
export {}
const dog = {
name: `小黄`,
friends: [
{
name: `小红`,
},
],
}
// 1.首先new一个Proxy对象
let proxy = new Proxy(dog, {
// 2.参数一为需要代理的数据,参数二为上图可以代理的13种的配置对象
get(target, property) {
// 3.参数1为上面dog对象,参数2为dog的属性
console.log(`get被监控到了`)
return target[property]
},
set(target, property, value, obj) {
// 4.参数1为上面dog对象,参数2为dog的属性,参数3为设置的新值
// 有点类似Object.defineProperty
console.log(obj)
console.log(target, property, value)
console.log(`set被监控到了`)
target[property] = value
},
})
// 那么接下来我们设置一下这个属性
// Dog.name = '小红' // set值时,发现不会打印 'set被监控到了'
// Dog.name // get值时,发现不会打印 'get被监控到了'
// 思考:为什么在set/get值的时候不会打印出来我们需要的东西呢?
// 上面说得很明白了,proxy相当于是一个壳,代理我们需要监控的数据,也就是我们要通过proxy来访问内部数据才会被监控到
proxy.name = `小红` // 打印输出 'set被监控到了'
console.log(proxy.name)
export {}
ts
let dictionary = {
Hello: 'Hola',
Bye: 'Adiós',
}
dictionary = new Proxy(dictionary, {
get(target, phrase) {
// 拦截读取属性操作
if (phrase in target) {
//如果字典包含该短语
return target[phrase] // 返回译文
} else {
// 否则返回未翻译的短语
return phrase
}
},
})
console.log(dictionary['Hello'])
console.log(dictionary['welcome to beijing'])
export {}
let dictionary = {
Hello: 'Hola',
Bye: 'Adiós',
}
dictionary = new Proxy(dictionary, {
get(target, phrase) {
// 拦截读取属性操作
if (phrase in target) {
//如果字典包含该短语
return target[phrase] // 返回译文
} else {
// 否则返回未翻译的短语
return phrase
}
},
})
console.log(dictionary['Hello'])
console.log(dictionary['welcome to beijing'])
export {}
ts
let numbers = []
numbers = new Proxy(numbers, {
// (*)
set(target, prop, val) {
// 拦截写入操作
if (typeof val == 'number') {
target[prop] = val
return true
} else {
return false
}
},
})
numbers.push(1) // 添加成功
numbers.push(2) // 添加成功
console.log('Length is: ' + numbers.length) // 2
try {
numbers.push('test')
} catch (error) {
console.log('有错误', error)
} // TypeError (proxy 的 `set` 操作返回 false)
let numbers = []
numbers = new Proxy(numbers, {
// (*)
set(target, prop, val) {
// 拦截写入操作
if (typeof val == 'number') {
target[prop] = val
return true
} else {
return false
}
},
})
numbers.push(1) // 添加成功
numbers.push(2) // 添加成功
console.log('Length is: ' + numbers.length) // 2
try {
numbers.push('test')
} catch (error) {
console.log('有错误', error)
} // TypeError (proxy 的 `set` 操作返回 false)
ts
let user = {
name: 'John',
age: 30,
_password: '***',
}
user = new Proxy(user, {
ownKeys(target) {
return Object.keys(target).filter((key) => !key.startsWith('_'))
},
})
// "ownKeys" 过滤掉 _password
for (let key in user) console.log(key) // name,然后是 age
// 对这些方法同样有效:
console.log(Object.keys(user)) // name,age
console.log(Object.values(user)) // John,30
// 我们使用 ownKeys 钩子拦截 for..in 对 user 的遍历,还使用 Object.keys 和 Object.values 来跳过以下划线 _ 开头的属性:
let user = {
name: 'John',
age: 30,
_password: '***',
}
user = new Proxy(user, {
ownKeys(target) {
return Object.keys(target).filter((key) => !key.startsWith('_'))
},
})
// "ownKeys" 过滤掉 _password
for (let key in user) console.log(key) // name,然后是 age
// 对这些方法同样有效:
console.log(Object.keys(user)) // name,age
console.log(Object.values(user)) // John,30
// 我们使用 ownKeys 钩子拦截 for..in 对 user 的遍历,还使用 Object.keys 和 Object.values 来跳过以下划线 _ 开头的属性:
ts
let user = {
name: 'John',
_password: '***',
}
user = new Proxy(user, {
get(target, prop) {
if (prop.startsWith('_')) {
throw new Error('Access denied')
}
let value = target[prop]
return typeof value === 'function' ? value.bind(target) : value // (*)
},
set(target, prop, val) {
// 拦截写入操作
if (prop.startsWith('_')) {
throw new Error('Access denied')
} else {
target[prop] = val
return true
}
},
deleteProperty(target, prop) {
// 拦截属性删除
if (prop.startsWith('_')) {
throw new Error('Access denied')
} else {
delete target[prop]
return true
}
},
ownKeys(target) {
// 拦截读取属性列表
return Object.keys(target).filter((key) => !key.startsWith('_'))
},
})
// “get” 不允许读取 _password
try {
console.log(user._password) // Error: Access denied
} catch (e) {
console.log(e.message)
}
// “set” 不允许写入 _password
try {
user._password = 'test' // Error: Access denied
} catch (e) {
console.log(e.message)
}
// “deleteProperty” 不允许删除 _password 属性
try {
delete user._password // Error: Access denied
} catch (e) {
console.log(e.message)
}
// “ownKeys” 过滤排除 _password
for (let key in user) console.log(key) // name
let user = {
name: 'John',
_password: '***',
}
user = new Proxy(user, {
get(target, prop) {
if (prop.startsWith('_')) {
throw new Error('Access denied')
}
let value = target[prop]
return typeof value === 'function' ? value.bind(target) : value // (*)
},
set(target, prop, val) {
// 拦截写入操作
if (prop.startsWith('_')) {
throw new Error('Access denied')
} else {
target[prop] = val
return true
}
},
deleteProperty(target, prop) {
// 拦截属性删除
if (prop.startsWith('_')) {
throw new Error('Access denied')
} else {
delete target[prop]
return true
}
},
ownKeys(target) {
// 拦截读取属性列表
return Object.keys(target).filter((key) => !key.startsWith('_'))
},
})
// “get” 不允许读取 _password
try {
console.log(user._password) // Error: Access denied
} catch (e) {
console.log(e.message)
}
// “set” 不允许写入 _password
try {
user._password = 'test' // Error: Access denied
} catch (e) {
console.log(e.message)
}
// “deleteProperty” 不允许删除 _password 属性
try {
delete user._password // Error: Access denied
} catch (e) {
console.log(e.message)
}
// “ownKeys” 过滤排除 _password
for (let key in user) console.log(key) // name
ts
let range = {
start: 1,
end: 10,
}
range = new Proxy(range, {
has(target, prop) {
return prop >= target.start && prop <= target.end
},
})
console.log(5 in range) // true
console.log(50 in range) // false
let range = {
start: 1,
end: 10,
}
range = new Proxy(range, {
has(target, prop) {
return prop >= target.start && prop <= target.end
},
})
console.log(5 in range) // true
console.log(50 in range) // false
ts
const a = {}
const b = { key: 'b' }
const c = { key: 'c' }
a[b] = 123
a[c] = 456
console.log(a[b])
// 对象键自动转换为字符串;
const a = {}
const b = { key: 'b' }
const c = { key: 'c' }
a[b] = 123
a[c] = 456
console.log(a[b])
// 对象键自动转换为字符串;
ts
let user = {
name: 'John',
}
user = new Proxy(user, {
get(target, prop, receiver) {
console.log(`GET ${prop}`)
return Reflect.get(target, prop, receiver) // (1)
},
set(target, prop, val, receiver) {
console.log(`SET ${prop}=${val}`)
return Reflect.set(target, prop, val, receiver) // (2)
},
})
console.log(user)
// console.log(Object.prototype.toString.call(user));
let name = user.name // shows "GET name"
user.name = 'Pete' // shows "SET name=Pete"
let user = {
name: 'John',
}
user = new Proxy(user, {
get(target, prop, receiver) {
console.log(`GET ${prop}`)
return Reflect.get(target, prop, receiver) // (1)
},
set(target, prop, val, receiver) {
console.log(`SET ${prop}=${val}`)
return Reflect.set(target, prop, val, receiver) // (2)
},
})
console.log(user)
// console.log(Object.prototype.toString.call(user));
let name = user.name // shows "GET name"
user.name = 'Pete' // shows "SET name=Pete"
reflect
js
const z = { w: `Super Hello` }
const y = { x: `hello`, __proto__: z }
console.log(Reflect.getOwnPropertyDescriptor(y, `x`))
console.log(Reflect.has(y, `w`))
console.log(Reflect.ownKeys(y, `w`))
console.log(Reflect.has(y, `x`))
console.log(Reflect.deleteProperty(y, `x`))
console.log(Reflect.has(y, `x`))
const z = { w: `Super Hello` }
const y = { x: `hello`, __proto__: z }
console.log(Reflect.getOwnPropertyDescriptor(y, `x`))
console.log(Reflect.has(y, `w`))
console.log(Reflect.ownKeys(y, `w`))
console.log(Reflect.has(y, `x`))
console.log(Reflect.deleteProperty(y, `x`))
console.log(Reflect.has(y, `x`))
js
{
console.log(`________________________________________________`)
const obj = new Proxy(
{},
{
get(target, key, receiver) {
console.log(`getting ${key}!`)
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
console.log(`setting ${key}!`)
return Reflect.set(target, key, value, receiver)
},
}
)
}
{
console.log(`________________________________________________`)
const handler = {
get: (target, name) => (name in target ? target[name] : 29),
}
const p = new Proxy({}, handler)
p.a = 1
p.b = undefined
console.log(`c` in p, p.c)
}
{
console.log(`________________________________________________`)
const obj = new Proxy(
{},
{
get(target, key, receiver) {
console.log(`getting ${key}!`)
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
console.log(`setting ${key}!`)
return Reflect.set(target, key, value, receiver)
},
}
)
}
{
console.log(`________________________________________________`)
const handler = {
get: (target, name) => (name in target ? target[name] : 29),
}
const p = new Proxy({}, handler)
p.a = 1
p.b = undefined
console.log(`c` in p, p.c)
}
get和set
js
const data = [1, 2, 3]
const p = new Proxy(data, {
get(target, key, receiver) {
console.log(`get value:`, key)
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
console.log(`set value:`, key, value)
return Reflect.set(target, key, value, receiver)
},
})
p.push(1)
// Get value: push
// Get value: length
// Set value: 3 1
// Set value: length 4
const data = [1, 2, 3]
const p = new Proxy(data, {
get(target, key, receiver) {
console.log(`get value:`, key)
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
console.log(`set value:`, key, value)
return Reflect.set(target, key, value, receiver)
},
})
p.push(1)
// Get value: push
// Get value: length
// Set value: 3 1
// Set value: length 4
proxy构造函数
js
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
say() {
console.log(`my name is ${this.name}, and my age is ${this.age}`)
}
}
const proxyTrack = (targetClass) => {
const prototype = targetClass.prototype
Object.getOwnPropertyNames(prototype).forEach((name) => {
targetClass.prototype[name] = new Proxy(prototype[name], {
apply(target, context, args) {
console.time()
target.apply(context, args)
console.timeEnd()
},
})
})
return new Proxy(targetClass, {
construct(target, args) {
const obj = new target(...args)
return new Proxy(obj, {
get(target, prop) {
console.log(`${target.name}.${prop} is being getting`)
return target[prop]
},
})
},
})
}
const MyClass = proxyTrack(Person)
const myClass = new MyClass('tom', 21)
myClass.say()
myClass.name
export {}
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
say() {
console.log(`my name is ${this.name}, and my age is ${this.age}`)
}
}
const proxyTrack = (targetClass) => {
const prototype = targetClass.prototype
Object.getOwnPropertyNames(prototype).forEach((name) => {
targetClass.prototype[name] = new Proxy(prototype[name], {
apply(target, context, args) {
console.time()
target.apply(context, args)
console.timeEnd()
},
})
})
return new Proxy(targetClass, {
construct(target, args) {
const obj = new target(...args)
return new Proxy(obj, {
get(target, prop) {
console.log(`${target.name}.${prop} is being getting`)
return target[prop]
},
})
},
})
}
const MyClass = proxyTrack(Person)
const myClass = new MyClass('tom', 21)
myClass.say()
myClass.name
export {}
proxy校验
js
// 验证规则
const validators = {
name: {
validate(value) {
return value.length > 6
},
message: '用户名长度不能小于六',
},
password: {
validate(value) {
return value.length > 10
},
message: '密码长度不能小于十',
},
moblie: {
validate(value) {
return /^1(3|5|7|8|9)[0-9]{9}$/.test(value)
},
message: '手机号格式错误',
},
}
// 验证方法
function validator(obj, validators) {
return new Proxy(obj, {
set(target, key, value) {
const validator = validators[key]
if (!validator) {
target[key] = value
} else if (validator.validate(value)) {
target[key] = value
} else {
alert(validator.message || '')
}
},
})
}
let form = {}
form = validator(form, validators)
form.name = '666' // 用户名长度不能小于六
form.password = '113123123123123'
// 验证规则
const validators = {
name: {
validate(value) {
return value.length > 6
},
message: '用户名长度不能小于六',
},
password: {
validate(value) {
return value.length > 10
},
message: '密码长度不能小于十',
},
moblie: {
validate(value) {
return /^1(3|5|7|8|9)[0-9]{9}$/.test(value)
},
message: '手机号格式错误',
},
}
// 验证方法
function validator(obj, validators) {
return new Proxy(obj, {
set(target, key, value) {
const validator = validators[key]
if (!validator) {
target[key] = value
} else if (validator.validate(value)) {
target[key] = value
} else {
alert(validator.message || '')
}
},
})
}
let form = {}
form = validator(form, validators)
form.name = '666' // 用户名长度不能小于六
form.password = '113123123123123'
array push
js
const handle = (params) => {
if (Array.isArray(params)) {
return params.reduce((accumulator, currentValue) => {
typeof currentValue === 'object'
? accumulator.push(handle(currentValue))
: accumulator.push(currentValue)
return accumulator
}, [])
} else {
return Reflect.ownKeys(params).reduce((accumulator, currentValue) => {
typeof params[currentValue] === 'object'
? (accumulator[currentValue] = handle(params[currentValue]))
: (accumulator[currentValue] = params[currentValue])
return accumulator
}, {})
}
}
let a = [
{
age: '23',
name: 334,
},
{ time: 'ee', date: new Date() },
]
b = handle(a)
b.push({ naa: 'erer' })
console.log(b)
console.log(a)
export {}
const handle = (params) => {
if (Array.isArray(params)) {
return params.reduce((accumulator, currentValue) => {
typeof currentValue === 'object'
? accumulator.push(handle(currentValue))
: accumulator.push(currentValue)
return accumulator
}, [])
} else {
return Reflect.ownKeys(params).reduce((accumulator, currentValue) => {
typeof params[currentValue] === 'object'
? (accumulator[currentValue] = handle(params[currentValue]))
: (accumulator[currentValue] = params[currentValue])
return accumulator
}, {})
}
}
let a = [
{
age: '23',
name: 334,
},
{ time: 'ee', date: new Date() },
]
b = handle(a)
b.push({ naa: 'erer' })
console.log(b)
console.log(a)
export {}
js
function extend(sup, base) {
let descriptor = Object.getOwnPropertyDescriptor(
base.prototype,
'constructor'
)
base.prototype = Object.create(sup.prototype)
const handler = {
construct(target, args) {
let obj = Object.create(base.prototype)
this.apply(target, obj, args)
return obj
},
apply(target, that, args) {
sup.apply(that, args)
base.apply(that, args)
},
}
let proxy = new Proxy(base, handler)
descriptor.value = proxy
Object.defineProperty(base.prototype, 'constructor', descriptor)
return proxy
}
let Person = function (name) {
this.name = name
}
let Boy = extend(Person, function (name, age) {
this.age = age
})
Boy.prototype.sex = 'M'
let Peter = new Boy('Peter', 13)
console.log(Peter.sex) // "M"
console.log(Peter.name) // "Peter"
console.log(Peter.age) // 13
function extend(sup, base) {
let descriptor = Object.getOwnPropertyDescriptor(
base.prototype,
'constructor'
)
base.prototype = Object.create(sup.prototype)
const handler = {
construct(target, args) {
let obj = Object.create(base.prototype)
this.apply(target, obj, args)
return obj
},
apply(target, that, args) {
sup.apply(that, args)
base.apply(that, args)
},
}
let proxy = new Proxy(base, handler)
descriptor.value = proxy
Object.defineProperty(base.prototype, 'constructor', descriptor)
return proxy
}
let Person = function (name) {
this.name = name
}
let Boy = extend(Person, function (name, age) {
this.age = age
})
Boy.prototype.sex = 'M'
let Peter = new Boy('Peter', 13)
console.log(Peter.sex) // "M"
console.log(Peter.name) // "Peter"
console.log(Peter.age) // 13