// 等价
const obj = { foo: 1 };
obj.foo;
Reflect.get(obj, "foo");
const obj = { foo: 1 };
Reflect.get(obj, "foo", { foo: 2 }); //输出是2
const obj = {
foo: 1,
get bar() {
return this.foo; // this.foo指的是obj.foo,期望应该是p.foo(代理后的对象)
},
};
effect(() => {
console.log(p.bar);
});
p.foo++;
// 副作用不会执行,原因同标题
const p = new Proxy(obj,{
get(target,key,receiver){
track(target,key)
return Reflect.get(target,key,receiver)
}
})
函数会部署内部方法[[Call]],普通对象不会
- 表 5-1 11 个内置方法都必须使用 ECMA 规范实现
- 内部方法[[Call]]必须使用 ECMA 规范实现
- 内部方法[[Construct]]必须使用 ECMA 规范实现
任意一条不符合就是异质对象,proxy 就是异质对象
创建代理对象时指定拦截函数,实际上是用自定义代理对象本身的内部方法和行为,而不是被代理对象的
const obj = { foo: 1 };
const p = new Proxy(obj, {
has(target, key) {
track(target, key);
return Reflect.has(target, key);
},
});
// obj就是被for...in的对象
function* EnumerateObjectProperties(obj) {
const visited = new Set();
for (const key of Reflect.ownKeys(obj)) {
if (typeof key === "symbol") continue;
const desc = Reflect.getOwnProprotyDescriptor(key);
if (desc) {
visited.add(key);
if (desc.enumerable) yield key;
}
}
const proto = Reflect.getPrototypeOf(obj);
if (proto === null) {
return;
}
for (const protoKey of EnumerateObjectProperties(proto)) {
if (visited.has(protoKey)) continue;
yield protoKey;
}
}
const obj = { foo: 1 };
const ITERATE_KEY = Symbol()
const p = new Proxy(obj, {
ownKeys(target, key) {
track(target, ITERATE_KEY);
return Reflect.ownKeys(target);
},
});
const p = new Proxy(obj, {
deleteProperty(target, key) {
const hadKey = Object.prototype.hasOwnProperty.call(target, key);
const res = Reflect.deleteProperty(obj, target);
if (hadKey && res) {
trigger(target, key, "DELETE");
}
return res;
},
});
function reactive(obj) {
return new Proxy(obj, {});
}
var a = {
bar: 1,
};
var b = {};
var x = new Proxy(a, {
set(target, key, value, receiver) {
console.log("a", target, receiver);
},
get(target, key, value, receiver) {
return Reflect.get(target, key, value, receiver);
},
});
var y = new Proxy(b, {
set(target, key, value, receiver) {
Reflect.set(target, key, value, receiver);
console.log("b", target, receiver);
},
get(target, key, value, receiver) {
return Reflect.get(target, key, value, receiver);
},
});
Object.setPrototypeOf(y, x);
y.bar = 2;
// a ...receiver 是child
// b ...receiver 是child
function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
if (key === "raw") {
return target;
}
},
set(target, key, newVal, receiver) {
//过滤掉parent的set
if (target === receiver.raw) {
///触发更新
}
},
});
}
function createReactive(obj,isShallow = false) {
reutrn new Proxy(obj, {
get(target,key,receiver){
if (key === "raw") {
return target;
}
const res = Reflect.get(target,key,receiver )
if(isShallow) {
return res
}
track(target,key)
if(typeof res === 'object' && res !== null) {
return reactive(res)
}
}
})
}
// 修改
arr[100] = "465654";
function set(target, key) {
//...
const type = Array.isArray(target)
? Number(key) < target.length
? "SET"
: "ADD"
: Object.prototype.hasOwnProperty.call(target, key)
? "SET"
: "ADD";
}
function trigger(target, key, type) {
if (type === "ADD" && Array.isArray(target)) {
const lengthEffects = depsMap.get("length");
lengthEffects &&
lengthEffects.forEach((effect) => {
if (effectFn !== activeEffect) {
effectsToRun.add(effectFn);
}
});
}
}
// 访问索引大于等于新length,要执行副作用
function trigger(target, ke+y, type, newVal) {
if (Array.isArray(target) && key === "length") {
if (key >= newVal) {
effects.forEach((effectFn) => {
/*...*/
});
}
}
}
function createReactive(obj) {
return new Proxy(obj, {
ownKeys(target) {
track(Array.isArray(target) ? "length" : ITERATE_KEY);
return Reflect.ownKeys(target);
},
});
}
Array.prototype.values === Array.prototype[Symbol.iterator];
let a = [1, 2, 3];
for (const i of a) {
}
for (const i of a.values()) {
}
const reactiveMap = new Map();
function reactive(obj) {
const existionProxy = reactiveMap.get(obj);
if (existionProxy) {
return existionProxy;
}
const proxy = createProxy(obj);
existionProxy.set(obj, proxy);
return proxy;
}
const arrayInstrumentations = {}
function get(target,key,receiver) {
if(Array.isArray(target) && arrayInstrumentations.hasOwnProperty(key) ){
Reflect.get(arrayInstrumentations,key,receiver)
}
}
const originMethod = Array.prototype.includes
const arrayInstrumentations = {
includes(...args) {
let res = originMethod.apply(this,args)
if(res === false) {
res = originMethod.apply(this.raw,args)
}
}
}
let shouldTrack = true["push"].forEach((method) => {
const originMethod = Array.prototype[method];
arrayInstrumentations[method] = function (...args) {
shouldTrack = false;
let res = originMethod.apply(this, args);
shouldTrack = true;
return res;
};
});