惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
C
Cisco Blogs
The Hacker News
The Hacker News
T
Tor Project blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The GitHub Blog
The GitHub Blog
A
Arctic Wolf
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The Register - Security
The Register - Security
云风的 BLOG
云风的 BLOG
Simon Willison's Weblog
Simon Willison's Weblog
P
Palo Alto Networks Blog
Vercel News
Vercel News
C
CERT Recently Published Vulnerability Notes
I
InfoQ
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
M
MIT News - Artificial intelligence
I
Intezer
aimingoo的专栏
aimingoo的专栏
U
Unit 42
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LINUX DO - 热门话题
Microsoft Security Blog
Microsoft Security Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Cyberwarzone
Cyberwarzone
P
Proofpoint News Feed
P
Proofpoint News Feed
B
Blog
T
Threat Research - Cisco Blogs
博客园 - 叶小钗
Recorded Future
Recorded Future
Last Week in AI
Last Week in AI
N
News and Events Feed by Topic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
Engineering at Meta
Engineering at Meta
G
Google Developers Blog
PCI Perspectives
PCI Perspectives
Google DeepMind News
Google DeepMind News
WordPress大学
WordPress大学
Application and Cybersecurity Blog
Application and Cybersecurity Blog
MyScale Blog
MyScale Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Schneier on Security
Schneier on Security
N
News | PayPal Newsroom
C
Cybersecurity and Infrastructure Security Agency CISA
H
Help Net Security
博客园 - 聂微东
H
Hackread – Cybersecurity News, Data Breaches, AI and More
G
GRAHAM CLULEY

Aimee's Blog

微服务与服务拆分:何时拆、怎么拆 异步与事件驱动架构:把协作从「打电话」改成「发消息」 高可用设计:怎么让系统尽量不宕机 可扩展性设计:怎么让系统加机器就能扛更多 缓存架构:多级缓存怎么搭 高并发三板斧:限流、熔断、降级 架构设计到底在设计什么 —— 从单体到微服务的演进 服务成本账:一个服务一个月烧多少钱 可观测性:线上出问题怎么查 API 设计:好接口长什么样 消息队列:为什么要 MQ,以及丢失、重复、顺序怎么破 查询优化:慢查询怎么治 —— 索引 + 预聚合 缓存:为什么快、三大坑、和数据库怎么保持一致 存储与基建选型 —— 传统业务 vs AI 大模型时代 权限系统怎么设计?—— 从 RBAC 到 Google Zanzibar 鉴权怎么落地?—— 常见业务场景的方案选型与避坑 JWT、OAuth、Token 刷新 —— 一个全栈工程师的鉴权入门笔记 我把跑了五年的旧博客升级到了 3.0 大模型 AIGC 满天飞 推荐一些学习和资料网站 2024 冒个泡 冒个泡 阿里云新机器安装 自定义配置 vue 的 webpack.config.js 从输入url到页面展示 React API 使用demo 欢迎加入 aimee前端技术交流群 github actions 自动化部署 很久以前的美食美荟 无穷之路纪录片还不错哦 vue 模板编译和组件化 vue2 响应式原理 vue2 虚拟DOM原理 vue2 源码解析-初始化 vue2.0 router及简易实现 防抖和节流 git rebase
Proxy 和 Object.defineProperty
Aimee · 2021-10-26 · via Aimee's Blog

Proxy

定义

Proxy主要用于改变对象属性的默认访问行为,在目标对象之前架设一层"拦截",外界对该属性的访问,都需先通过这一层拦截,因此提供了一层机制,可对外界的访问进行过滤和改写。 ​

用法:

/*
 * target: 目标对象
 * handler: 配置对象,用来定义拦截的行为
 * oproxy: Proxy构造器的实例
 */
const obj = {}
const handler = {
	get(target, key,receiver){ // 拦截对象属性的读取
		console.log('get')
    return Reflect.get(target, key,receiver)
	},
  set(target, key, value, receiver){ // 拦截对象属性的设置
		console.log('set')
    return Reflect.set(target, key, value, receiver)
	},
  has(target, key){ // 拦截propKey in proxy 操作
    console.log('has')
  	return Reflect.has(target, key)
  },
  deleteProperty(target, key){// 拦截delete proxy[propKey] 操作 返回一个布尔值
    console.log('deleteProperty')
  	return Reflect.deleteProperty(target, key)
  },
  defineProperty(target, key, desc){ // 拦截Object.defineProperty(proxy, key, desc)/Object.defineProperties(proxy,decs)  返回一个布尔值
  	return Reflect.defineProperty(target, key,desc)
  },
  construct(target, args){ // 拦截 proxy实例作为构造函数实例化的操作,比如 new proxy(...args)
  	 console.log('construct')
    return Reflect.construct(target, args)
  },
  ownKeys(target){ //getOwnPropertyNames(proxy) / getOwnPropertySymbols(proxy)/for...in/Object.keys(proxy),返回一个数组。Object.keys,而Object.keys()返回结果仅包括目标对象可遍历的属性
  	console.log('ownKeys')
    return Reflect.ownKeys(target)
  },
  getOwnPropertyDescriptor(target,key){//拦截Object.getOwnPropertyDescriptor(), 返回属性的的描述对象
  	console.log('getOwnPropertyDescriptor')
    return Reflect.getOwnPropertyDescriptor(target,key)
  },
  preventExtensions(target){ // 拦截Object.preventExtensions(proxy), 返回一个布尔值
  	console.log('preventExtensions')
    return Reflect.preventExtensions(target)
  },
  getPrototypeOf(target){ // 拦截Object.getPrototyOf(proxy), 返回一个对象
  	console.log('getPrototypeOf')
    return Reflect.getPrototypeOf(target)
  },
  setPrototypeOf(target, proto){// 拦截Object.setPrototyOf(proxy,proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
  	console.log('setPrototypeOf')
    return Reflect.setPrototypeOf(target, proto)
  },
  apply(target,object ,args){//拦截proxy实例作为函数时的调用,比如proxy(...args)/proxy.call(object, ...args)/proxy.apply(...args)
  	console.log('apply')
    return Reflect.apply(target, object ,args)
  },
  isExtensible(target){// 拦截Object.isExtensible(), 返回一个布尔值
  	console.log('isExtensible')
    return Reflect.isExtensible(target)
  } 
  
}
const oproxy = new Proxy(obj, handler)
obj.a = 1
console.log(oproxy.a)// 

Proxy代理的对象属性是外层的,如果需要属性值对象进行代理,可以通过递归设置代理。

设置内层属性递归代理

const obj = {
	a: 1,
  objb: {
		c: 2
  }
}
const handler = {
	get(target, key, receiver){
    console.log('get')
    const value = target[key]
  	if(value !== 'null' && typeof value === 'object'){
    	return new Proxy(value, handler)
    }
    return Reflect.get(target, key, receiver)
  },
  set(target, key, value, receiver){
  	return Reflect.set(target, key, value, receiver)
  }
}

const oproxy = new Proxy(obj, handler)
oproxy.objb.c
// 输出
// get
// get
// 2

Object.defineProperty

定义

Object.defineProperty()直接在对象定义新属性,或者修改对象上的现有属性,并返回该对象。 ​

用法:

/*
* obj 要在其上定义或修改属性的对象
* prop 要定义或修改的属性的名称或者Symbol
* descriptor 定义或修改的属性描述符
*/
Object.defineProperty(obj, prop, descriptor)

描述符: 分为数据描述符和存取描述符,一个描述符只能是其中的一个,不能同时是两者。

  • 数据描述符:有值的属性,该值是否可重写。
  • 存取描述符:由getter 和setter函数所描述的属性。

共享属性: 1、configurable 表示可配置的,默认为false。当为true时,该属性的描述符才可以被改变,同时该属性可以被删除。 ​

2、enumrable 表示可枚举的,默认为false。当为true时,该属性才会在对象枚举时枚举到。 ​

数据描述符特有属性: 1、value 表示属性对应的值,默认为undefined 2、writable 表示属性是否可修改的,默认为false。只有值为true时,属性的值才可以被修改运算符修改成功。

const obj = {}
Object.defineProperty(obj, 'name', {
	configurable: true,
  enumrable: true,
  value: 'jack',
  writable: true
})

存取描述符特有属性: **1、get ** 当获取属性值的时候就会执行getter函数,该函数返回一个值, 默认为undefined 2、set 当设置属性值的时候就会执行setter函数

const obj = {}
Object.defineProperty(obj, 'name',{
  configurable: true,
  enumrable: true,
  get(){
    console.log('get--name')
		return 'jack'
	},
	set(value){
		console.log('set---name')
    return value
	}
})

Proxy和Object.defineProperty 对比:

  • Proxy是对整个对象的代理,而Object.defineProperty是代理对象的单个属性。
  • 对象上新增属性,Proxy可以监听到,而Object.defineProperty不可以
  • 数组新增修改,Proxy可以监听到,而Object.defineProperty不可以
  • 若对象内部的所有属性均要递归监听,Proxy可以只在调用的时候监听,而Object.defineProperty需要一次全部实现监听,性能比Proxy差
  • Proxy不兼容ie, Object.defineProperty不兼容ie8以下
  • Proxy使用上比Object.defineProperty更方便