Object.defineProperties()与Proxy对象代理

Posted qqprincekin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Object.defineProperties()与Proxy对象代理相关的知识,希望对你有一定的参考价值。

Object.defineProperties()

了不起啊。。vue.js通过它实现双向绑定的 

Object.defineProperties(obj,props) 方法直接在一个对象上定义新的属性或修改现有属性 并返回该对象

参数

obj在其上定义或修改属性的对象

props要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器

描述符具有以下键:

  configurable
true 当且仅当该属性描述符的类型可以被改变并且该属性可以从对应对象中删除
默认为 false
  enumerable
true 当且仅当在枚举相应对象上的属性时该属性显现
默认为 false
  value
与属性关联的值。可以是任何有效的javascript值(数字,对象,函数等)
默认为 undefined.
  writable
true当且仅当与该属性相关联的值可以用assignment operator改变时
默认为 false
  get
作为该属性的 getter 函数,如果没有 getter 则为undefined。函数返回值将被用作属性的值
默认为 undefined
  set
作为属性的 setter 函数,如果没有 setter 则为undefined。函数将仅接受参数赋值给该属性的新值
默认为 undefined
 返回值
传递给函数的对象
 
用法
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参数

targetProxy包装的目标对象(要被代理的对象可以是任何类型的对象 包括原生数组 函数 甚至另一个代理)

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 = "王瘦瘦" //报错 不允许比老赵帅!!

 

Feeling so high but too far away








以上是关于Object.defineProperties()与Proxy对象代理的主要内容,如果未能解决你的问题,请参考以下文章

Object.defineProperties()与Proxy对象代理

使用Object.Defineproperties改变对象数据结构

Object 的静态方法之 defineProperties 以及数据劫持效果

深入理解Object.defineProperty

Object.create 方法

Object备忘录