好久没有写博客啦,两个月干嘛了呢。
琢磨了一下手撕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;
}
}