Object.defineProperties()
了不起啊。。vue.js通过它实现双向绑定的
Object.defineProperties(obj,props)
方法直接在一个对象上定义新的属性或修改现有属性 并返回该对象
参数
obj
在其上定义或修改属性的对象
props
要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器
描述符具有以下键:
-
true
当且仅当该属性描述符的类型可以被改变并且该属性可以从对应对象中删除
默认为false
-
true
当且仅当在枚举相应对象上的属性时该属性显现
默认为false
configurable
enumerable
-
与属性关联的值。可以是任何有效的JavaScript值(数字,对象,函数等)
默认为undefined
. -
true
当且仅当与该属性相关联的值可以用 assignment operator改变时
默认为false
value
writable
-
作为该属性的 getter 函数,如果没有 getter 则为
undefined
。函数返回值将被用作属性的值
默认为undefined
-
作为属性的 setter 函数,如果没有 setter 则为
undefined
。函数将仅接受参数赋值给该属性的新值
默认为undefined
get
set
var a= {} Object.defineProperty(a,"b",{ value:123 }) console.log(a.b);//123
第一个参数:目标对象
第二个参数:需要定义的属性或方法的名字
第三个参数:目标属性所拥有的特性(descriptor)
现在咱主要讲get跟set哈 !! (其他详情可参考MDN) https://developer.mozilla.org/zh-CN/
set 和 get
在 descriptor 中不能 同时设置访问器 (get 和 set) 和 wriable 或 value 否则会错 就是说想用(get 和 set) 就不能用(wriable 或 value中的任何一个)
set 和 get 他俩干啥用的
var a= {} Object.defineProperty(a,"b",{ set:function(newValue){ console.log("你要赋值给我 我的新值是"+newValue) }, get:function(){ console.log("你取我的值") return 2 //注意这里 我硬编码返回2 } }) a.b =1 //打印 你要赋值给我,我的新值是1 console.log(a.b) //打印 你取我的值 //打印 2 注意这里,和我的硬编码相同的
简单来说,, 这个 “b” 赋值 或者 取值的时候会分别触发 set 和 get 对应的函数 取值、赋值
JS proxy
Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)
记得前一段时间用它实现过原生的双向数据绑定
<html> <head> </head> <body> <input type="text" id='ipt' oninput='handle()' /> <div id='txt'></div> <button id='btn'>王瘦瘦</button>
<script> var obj = { mess:''" } var proxy = new Proxy(obj, { get: function(target) { return target.mess; }, set: function(target,key,value){ target.mess = value; txt.innerHTML = proxy.mess; } }); function handle(){ var val = ipt.value; //proxy添加了get和set方法 proxy.mess = val; } btn.onclick = function(){ console.log(proxy.mess); } </script>
</body>
</html>
Proxy是ES6中提供的新的API 可以用来定义对象各种基本操作的自定义行为
(在文档中被称为traps我觉得可以理解为一个针对对象各种行为的钩子)
拿它可以做很多有意思的事情 在我们需要对一些对象的行为进行控制时将变得非常有效
Proxy参数
target
用Proxy
包装的目标对象(要被代理的对象可以是任何类型的对象 包括原生数组 函数 甚至另一个代理)
handler
一个对象 其属性是当执行一个操作时定义代理的行为的函数(对该代理对象的各种操作行为处理)
语法
let target = {} let handlers = {} let proxy = new Proxy(target, handlers) proxy.a = 123 console.log(target.a) // 123
在第二个参数为空对象的情况下 基本可以理解为是对第一个参数做的一次浅拷贝
(proxy是浅拷贝 只是做的对象的代理)
target是代理为数组扩展的实用工具 可以灵活的“定义”属性 而不需要使用Object.defineProperties方法
var docCookies = new Proxy(docCookies, { "get": function (oTarget, sKey) { return oTarget[sKey] || oTarget.getItem(sKey) || undefined; }, "set": function (oTarget, sKey, vValue) { if (sKey in oTarget) { return false; } return oTarget.setItem(sKey, vValue); }, "deleteProperty": function (oTarget, sKey) { if (sKey in oTarget) { return false; } return oTarget.removeItem(sKey); }, "enumerate": function (oTarget, sKey) { return oTarget.keys(); }, "ownKeys": function (oTarget, sKey) { return oTarget.keys(); }, "has": function (oTarget, sKey) { return sKey in oTarget || oTarget.hasItem(sKey); }, "defineProperty": function (oTarget, sKey, oDesc) { if (oDesc && "value" in oDesc) { oTarget.setItem(sKey, oDesc.value); } return oTarget; }, "getOwnPropertyDescriptor": function (oTarget, sKey) { var vValue = oTarget.getItem(sKey); return vValue ? { "value": vValue, "writable": true, "enumerable": true, "configurable": false } : undefined; }, }); /* Cookies 测试 */ alert(docCookies.my_cookie1 = "First value"); alert(docCookies.getItem("my_cookie1")); docCookies.setItem("my_cookie1", "Changed value"); alert(docCookies.my_cookie1);
全部traps
在这里实现一个简单的对象保护 只读属性 实现数据的保护
let Person = { name : "老赵", age : 18 } let person = new Proxy(Person,{ get(target,key){ return target[key] //读操作 }, set(target,key,value){ if(key !== "name"){ target[key] = value } } })
//person.name = "王瘦瘦" //报错 不允许比老赵帅!!