day5 vue3源码学习之proxy 与 definepropety

61 阅读1分钟

1、Proxy

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

1. 基本操作(11种)

注:这里只列举了几种 ,其余的可以去MDN查看 Proxy - JavaScript | MDN (mozilla.org)``

// 为什么说是对象的基本操作呢,我们使用js对对象取值、赋值等基本操作就是在调用一个个函数

const obj = {
    a: 11
}
obj.a // [[GET]]
obj.b = 10 // [[SET]]
'a' in obj // [[HAS]]
delete obj a // [[DELETE]]
for(const key in obj){} // [[OWNKEYS]]

2. 拦截和自定义

当我们不使用 Proxy来代理对象的时候在操作对象时会默认调用原来的基本操作函数,当我们使用Proxy时他就不会走原来的函数了,会走我们proxy描述符中的陷阱函数(就像陷阱一样会拦截)

const obj = {
    browsers: ["Internet Explorer", "Netscape"],
}
// obj:目标对象
// prop:操作的键
// value: 赋的值
// 代理对象 = new Proxy(要代理的对象, {
//    get:(obj,prop){},
//    set:(obj,prop,value){},    
// })


// 以下`products`代理会计算传值并根据需要转换为数组。这个代理对象同时支持一个叫做 `latestBrowser`的
// 附加属性,这个属性可以同时作为 getter 和 setter。
let products = new Proxy(
  obj,
  {
    get: function (obj, prop) {
      // 附加一个属性
      if (prop === "latestBrowser") {
        return obj.browsers[obj.browsers.length - 1];
      }

      // 默认行为是返回属性值
      return obj[prop];
    },
    set: function (obj, prop, value) {
      // 附加属性
      if (prop === "latestBrowser") {
        obj.browsers.push(value);
        return;
      }

      // 如果不是数组,则进行转换
      if (typeof value === "string") {
        value = [value];
      }

      // 默认行为是保存属性值
      obj[prop] = value;

      // 表示成功
      return true;
    },
  },
);

console.log(products.browsers); // ['Internet Explorer', 'Netscape']
products.browsers = "Firefox"; // 如果不小心传入了一个字符串
console.log(products.browsers); // ['Firefox'] <- 也没问题,得到的依旧是一个数组

products.latestBrowser = "Chrome";
console.log(products.browsers); // ['Firefox', 'Chrome']
console.log(products.latestBrowser); // 'Chrome'

2. Object.definepropety