【ES6】关于Proxy和Reflect

好久没有写博客啦,两个月干嘛了呢。

琢磨了一下手撕promise,没琢磨通,通了的也快忘记了。

实习啦啦啦啦~学到了好多,查漏补缺。

最近可以自己看看Proxy和Reflect。有空了捋捋,写写自己的理解。先占个坑。

// 我想知道proxy到底用来做什么,代理
// let target = {age:12};
// let handler = {};
// let proxy = new Proxy(target, handler);
// console.log(target.name);
// console.log(target.age);
// console.log(proxy.name);
// console.log(proxy.age);
// proxy.name = "chailo";
// proxy.age = 18;
// console.log(target.name);
// console.log(target.age);
// console.log(proxy.name);
// console.log(proxy.age);


// let proxy = new Proxy(target, handler);
// 官方解释:Proxy可以理解成,在目标对象target之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截。或者说,“代理”。
// 我们可以通过proxy来修改target,在handler中设置内容可以对target进行一些操作。
// 👆如果handler是一个空对象,即handler没有设置任何拦截,那proxy就等同于target。Proxy 支持的拦截操作一共 13 种。


// 1️⃣ proxy作为其他对象的原型对象
// var proxy = new Proxy({}, {
//     get: function (target, propKey) {
//         return 35;
//     }
// });

// let obj = Object.create(proxy);
// obj.time = 33;
// console.log(obj.time);
// console.log(obj.title);
// obj对象本身并没有time属性,所以根据原型链,会在proxy对象上读取该属性。


// 2️⃣ 将 Proxy 对象,设置到object.proxy属性,从而可以在object对象上调用。
// ❓ 这个技巧有什么用呢
// ✅ 就是单纯的把它放到了对象里面,意思就是它可以作为对象的属性存在。
// let object = { proxy: new Proxy(target, handler) };

// ❓Reflect是什么作用呢
// function createArray(...elements) {
//     let handler = {
//         get(target, propKey, receiver) {
//             let index = Number(propKey);
//             if (index < 0) {
//                 propKey = String(target.length + index);
//             }
//             return Reflect.get(target, propKey, receiver);
//         }
//     };

//     let target = [];
//     target.push(...elements);
//     return new Proxy(target, handler);
// }

// let arr = createArray('a', 'b', 'c');
// arr[-1] // c


// var pipe = function (value) {
//     var funcStack = [];
//     var oproxy = new Proxy({}, {
//         get: function (pipeObject, fnName) {
//             if (fnName === 'get') {
//                 return funcStack.reduce(function (val, fn) {
//                     return fn(val);
//                 }, value);
//             }
//             funcStack.push(window[fnName]);
//             return oproxy;
//         }
//     });

//     return oproxy;
// }

// var double = n => n * 2;
// var pow = n => n * n;
// var reverseInt = n => n.toString().split("").reverse().join("") | 0;

// pipe(3).double.pow.reverseInt.get; // 63

// 遇到问题,分解问题,把所有的东西都放在了函数内。提取出来,函数变得轻便。
// 其实慢慢读,能得到结果。但是这个速度太慢了,所以应该寻找合适方法提高效率。
// var add = (n) => n + 1;
// var sub = (n) => n + 1;
// let obj1 = {
//     add,
//     sub
// }
// let arr = []
// var obj = new Proxy({}, {
//     get: function(target, property, receiver) {
//         if (property !== 'get') {
//             arr.push(property)
//             return receiver
//         } else {
//             return arr.reduce((val, fn) => {
//                 return obj1[fn](val)
//             }, 1)
//         }
//     }
// })
// console.log(obj.add.sub.get);

// var myObject = {
//     foo: 1,
//     bar: 2,
//     get baz() {
//       return this.foo + this.bar;
//     },
// }
// console.log(myObject.baz);      //结果:3
// console.log(myObject.baz());    //结果:❓报错 myObject.baz is not a function

// const handler = {
//   set: function(obj, prop, value, receiver) {
//     console.log(receiver);
//     obj[prop] = receiver;
//     return true;
//   }
// };

// const myObj = {};
// const proxy = new Proxy(myObj, handler);
// // Object.setPrototypeOf(myObj, proxy);

// myObj.foo = 'bar';
// myObj.foo === myObj // true



// src/components/UserRepositories.vue

export default {
  components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
  props: {
    user: { 
      type: String,
      required: true
    }
  },
  data () {
    return {
      repositories: [], // 1
      filters: { ... }, // 3
      searchQuery: '' // 2
    }
  },
  computed: {
    filteredRepositories () { ... }, // 3
    repositoriesMatchingSearchQuery () { ... }, // 2
  },
  watch: {
    user: 'getUserRepositories' // 1
  },
  methods: {
    getUserRepositories () {
      // 使用 `this.user` 获取用户仓库
    }, // 1
    updateFilters () { ... }, // 3
  },
  mounted () {
    this.getUserRepositories() // 1
  }
}
let obj = {
    a: '111',
    b: 'bbb',
    c: [1,2,3]
}
let rec1 = reactive(obj);
effect(() => {
    document.getElementsByTagName('h2')[0].innerText = rec1.a
})
function change(){
    console.log('change')
    rec1.a = Math.random()
}

// reactive.js
//WeakMap 的key 必须是对象

// objectList 避免对象重复proxy
const objectList = new WeakMap()//key: target, value: proxy

// proxyList 避免proxy对象再次被proxy
const proxyList = new WeakMap()//key: proxy, value: target

function reactive(target) {
    let proxy = objectList.get(target);
    //如果存在,即返回
    if (proxy !== void 0) {
        return proxy
    }
    // 如果target是proxy
    if (proxyList.has(target)) {
        return target
    }
    // 如果是基本类型,直接返回
    if (!isObject(target)) {
        return target
    }
    proxy = new Proxy(target, handle)
    objectList.set(target, proxy)
    proxyList.set(proxy, target)

    return proxy;

}
const handle = { get, set, deleteProperty };

function get(target, propKey, receiver) {
    console.log('get')
    let proxy = Reflect.get(target, propKey, receiver);
    track(target, 'get', propKey)
    return isObject(proxy) ? reactive(proxy) : proxy;
    //实现多层代理,若为对象,需要递归
}
function set(target, propKey, value, receiver) {
    const oldvalue = target[propKey];

    let proxy = Reflect.set(target, propKey, value, receiver)
    // 当是新增的属性 或者 数据变化时 ,trigger
    if (!target.hasOwnProperty(propKey)) {
        trigger(target, 'add', propKey)
    } else if (oldvalue !== value) {
        trigger(target, 'set', propKey)
    }
    return proxy
}
function deleteProperty(target, propKey) {
    console.log('删除')
    let proxy = Reflect.deleteProperty(target, propKey)
    trigger(target, 'delete', propKey)
    return proxy
}

//方法
function isObject(val) {
    return typeof val === 'object' && val !== null;
}

//effect.js

//收集依赖
let targetMap = new WeakMap()//所有依赖 key:obj


//get 时 收集依赖
function track(target, type, key) {
    console.log('track-收集依赖', type, target, key)

    if (effectFn) {
        let depsMap = targetMap.get(target);
        //targetMap无target对象,则新建
        if (depsMap === void 0) {
            console.log('无depsMap')
            targetMap.set(target, (depsMap = new Map()))
        }
        //depsMap无有key这个属性,则新建
        let dep = depsMap.get(key)
        if (dep === void 0) {
            console.log('无key')
            depsMap.set(key, (dep = new Set()))
        }
        // 放入依赖 effect就是依赖
        if (!dep.has(effectFn)) {
            console.log('无effect,并放入effect')
            dep.add(effectFn)
        }
    }
}

//set 时更新
function trigger(target, type, key) {
    console.log('trigger-触发依赖', type,key)

    let depsMap = targetMap.get(target)

    if (depsMap) {
        let deps = depsMap.get(key)
        if (deps) {
            //将当前key对应的effect一次执行
            deps.forEach(effect => {
                effect()
            })
            // 删除
            if(type == 'delete'){
                console.log('delete')
                depsMap.delete(key)
            }
        }
        
    }
}
//临时存放 effect中的fn参数
let effectFn = null;

function effect(fn) {
    try {
        console.log('try')
        effectFn = fn;
        fn();
    } finally {
        console.log('finally')
        effectFn = null;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值