案例:
let arr = [];
let proxyer = new Proxy(arr, {});
console.log(proxyer instanceof Proxy); // 报错:Uncaught TypeError: Function has non-object prototype 'undefined' in instanceof check
console.log(proxyer instanceof Array); // true
console.log(proxyer.__proto__.constructor); // Array() { [native code] }
new Proxy的实例和被代理的taget保持相同的引用类型,Proxy的实例的原型上也没有所谓的Proxy构造函数
那么如何判断一个元素是proxy类型呢?
使用Symbol.toStringTag
通俗理解就是可以改变Object.prototype.toString
的执行结果
// 例一
({[Symbol.toStringTag]: 'Foo'}.toString())
// "[object Foo]"
// 例二
class Collection {
get [Symbol.toStringTag]() {
return 'xxx';
}
}
let x = new Collection();
Object.prototype.toString.call(x) // "[object xxx]"
最终解决方案
Proxy = new Proxy(Proxy, {
//拦截 new 操作符,生成 Proxy 实例的时候来拦截
construct: function (target, argumentsList) {
//result是new Proxy()生成的原本的实例
const result = new target(...argumentsList);
//获取原本实例reslut的类型
const originToStringTag = Object.prototype.toString.call(result).slice(1,-1).split(' ')[1]
//改写result的[Symbol.toStringTag]属性,加上被代理的标志
result[Symbol.toStringTag] = 'Proxy-' + originToStringTag;
return result;
},
});
let a = new Proxy([],{})