Object.defineProperty 以及 Proxy对比和基本语法 实干vue3数据响应

一、Object.defineProperty是什么?

Object.defineProperty 是ES5Proxy 为开发者提供JavaScript已有却不能调用的功能,在ES5之前,js环境中的对象包含许多不可枚举和可枚举的属性,但是开发者不能自己定义可枚举和不可枚举,于是ES5引入了Object.definePeoperty()方法来支持去做js引擎早就可以实现的事情

1.Object.defineProperty 参数

Object.defineProperty(obj, prop, descriptor)

  1. obj 要定义的对象
  2. prop 要定义或修改的属性的名称或 Symbol
  3. descriptor要定义或修改的属性描述符。

使用 Object.defineProperty() 添加的属性值是不可修改的
代码如下(示例):

let obj = {};

let newObj = Object.defineProperty(obj, "OBJ", {
  value: { a: 1, b: 2, c: 3 },
});

obj === newObj // true
newObj.OBJ // { a: 1, b: 2, c: 3 }
//使用 Object.defineProperty() 添加的属性值是不可修改的
newObj.OBJ = 111;
newObj.OBJ // { a: 1, b: 2, c: 3 }
// 不可枚举的

添加的属性值是不可修改的

let obj = {};
let newObj = Object.defineProperty(obj, "b", {
  value: { a: 1},
});
newObj.b // {a:1}
newObj.b = 123
newObj.b // {a:1}

添加的属性值是不可修改的怎么变为可修改?
当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。
默认为 false。

let obj = {};
let newObj = Object.defineProperty(obj, "b", {
  value: { a: 1},
   writable: true,
});
newObj.b // {a:1}
newObj.b = 123
newObj.b // 123

删除属性

let obj = {};
let newObj = Object.defineProperty(obj, "b", {
  value: { a: 1},
});
delete newObj.OBJ;
newObj.OBJ // { a: 1},

怎么变为可删除属性?
当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
默认为 false

let obj = {};
let newObj = Object.defineProperty(obj, "b", {
  value: { a: 1},
  configurable :true
});
delete newObj.OBJ;
newObj.OBJ // undefined

delete 操作符可以从对象中删除某个属性,成功返回true,不成功返回false

如果尝试删除不可配置的属性则会抛出异常

'use strict';
	let target = {
			name:'target',
			value:12
		}
				
Object.defineProperty(target,'name',{configurable:false})
// Uncaught TypeError: Cannot delete property 'name' 
log(delete target.name)

Uncaught TypeError: Cannot delete property ‘name’ of #
这个错误在 Proxy 中可以得到解决

枚举和循环Object

let obj = { a: 1, b: 2, c: 3 };
Object.keys(obj) // [a,b,c]
for(let key in obj){
console.log(key) //a,b,c
}

禁止枚举和循环Object

let obj = {};

let newObj = Object.defineProperty(obj, "OBJ", {
  enumerable: false,
  value: { a: 1, b: 2, c: 3 },
  // enumerable: false,
});


console.log(Object.keys(newObj)); // []

// 不进,没有迭代属性
for (const key in newObj) {
  console.log(key);
}

使用get 和set 来监听但前对象的使用
使用get 和set的时候需要注意不能够代理对象的任何属性设置value,和writable 否者会出错 TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #
但是可以添加 enumerable 枚举属性 以及 configurable 是否可以被删除

let obj = {};

Object.defineProperty(obj, "a", {
  get: (data) => {
    console.log("getget", data);
  },
  set: (data) => {
    console.log("setset", data);
  },
});

obj.a = 1999;

obj.a;

一、Proxy是什么?

ES6添加了一些内置的3对象,赋予开发者更多的访问JavaScript引擎的能力,Proxy(代理)是可以拦截并且改变底层JavaScript引擎操作的包装器

Object.defineProperty 基本语法对比Proxy

let obj = {};

let neObj = Object.defineProperty(obj,'b',{})

console.log(obj === neObj); // true 因为修改的同一个数据源

let target = {};

let py = new Proxy(target, {});

console.log(py == target); //false py 是Proxy代理过的新的 Proxy 对象  target只是一个普通的对象
赋值对比

let target = {};

let py = new Proxy(target, {});

py.name = "自夏";
target.name = "哥哥";

console.log(py.name, target.name); //哥哥 哥哥

let obj = {};

let neObj = Object.defineProperty(obj, "b", { value: "bbba" });

console.log(obj.b, neObj.b); // bbba  bbba

obj.b = "obj.b";
neObj.b = "neObj.b";

console.log(obj.b, neObj.b); // bbba bbba
数据劫持 vue3

get(traTarget,key,receiver)
traTarget 代理目标对象
key 要读取属性的key 字符串或者是Symbol
receiver 操作发生的对象

set(traTarget,key ,value,receiver)
traTarget 代理目标对象
key 要写入的属性键(key)字符串或者是Symbol
value 要写入的属性值
receiver 操作发生的对象
deleteProperty(traTarget,propname)
traTarget 代理目标对象
propname 要删除的key

let user = {
					name:'selfsummer'
				}
				let newUser = new Proxy(user,{
					// 获取数据会触发
					get(traTarget,key,receiver){
						console.log(traTarget,key,receiver);
						return traTarget[key]
					},
					// 设置属性值,和添加属性值 会触发
					set(traTarget,key ,value,receiver){
						console.log(traTarget,key ,value,receiver);
						return traTarget[key] = value
					},
					// 删除属性
					deleteProperty(traTarget,propname){
						console.log(traTarget,propname);
					 return	delete traTarget[propname]
					}
				})
				
				
				console.log(newUser.name);
				
				console.log(newUser.sex = 'zixia');
				console.log(newUser.name);
				
				delete newUser.name

set

可以拦截写入属性的操作

	const {log} = console
				let user = {
					name:'selfsummer'
				}
				let newUser = new Proxy(user,{
					// 设置属性值,和添加属性值 会触发
					set(traTarget,key ,value,receiver){
						console.log(traTarget,key ,value,receiver);
						log(isNaN(key),value)
						// 当前是是存在该对象中
						if(traTarget.hasOwnProperty(key)){
							if(isNaN(value)){
								throw new TypeError('存在修改的属性要修改必须是数字')
							}
						}
						
						// return traTarget[key] = value
						return Reflect.set(traTarget,key ,value,receiver)
					},
				})
				
				
				newUser.name = 123
				
				// newUser.name = '自夏'  错误
				
				log(newUser.name) //自夏
				log(user.name) //自夏
				
					newUser.sex = '🚹'

get

可以拦截读取属性

	let user = {name:'selfsummer'}
	let newUser = new Proxy(user,{
						get(traTarget,key,receiver){
						
						if(!(key in traTarget)){
							throw new TypeError(`要读取的属性 ${key} 不存在 ${traTarget}`)
						}
						
						return traTarget[key]
					},
					}
				newUser.sex // 报错
				newUser.name //selfsummer

has

每当用 in 操作时都会调用 has 函数,并传入了二个参数
Reflect.has 也接受has 相同的参数,并且返回 in 操作默认返回值

Proxy 中的has函数 也可使用 in 操作符来实现,但是默认实现的函数是由 Reflect.has(traTarget,key) 来实现的 traTarget 为要要检测的对象 key 为要检测的属性

	let user = {
					name:'selfsummer'
				}
				let newUser = new Proxy(user,{
						/**
					 * @param {Object} traTarget 读取属性的对象
					 * @param {Object} key 要检查的属性
					 */
					has(traTarget,key){
						log(traTarget,key)
						// 使用in 来实现
						// key in traTarget
						return Reflect.has(traTarget,key)
					}
				}

deleteProperty

在 Proxy 中 使用delete 操作符来删除对象 回去调用 deleteProperty 他接受二个参数 (traTarget,key)

Reflect.deleteProperty() 方法为 deleteProperty 默认实现方法,接受同样而二个参数

let user = {
					name:'selfsummer'
				}
	const proxy = new Proxy(user,{
			deleteProperty(target,key){
				
				//return	delete traTarget[propname] 于下面代码实现效果相同
				return	Reflect.deleteProperty(target,key)
			}
	})
	
name in proxy // true
delete proxy.name // false

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值