Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/443.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么[[GetPrototypeOf]]是Javascript代理的不变量?_Javascript_Arrays_Proxy_Es6 Proxy - Fatal编程技术网

为什么[[GetPrototypeOf]]是Javascript代理的不变量?

为什么[[GetPrototypeOf]]是Javascript代理的不变量?,javascript,arrays,proxy,es6-proxy,Javascript,Arrays,Proxy,Es6 Proxy,Javascript代理对象的一个应用程序是,通过将数据作为数组数组通过线路发送,同时使用一个对象列出每个字段的字段名和索引(即字段映射),从而减少网络流量。(而不是在每个对象中重复属性名称的对象数组) 乍一看,ES6代理似乎是在客户端使用数据的一种很好的方式(即以数组为目标,以字段映射为基础的处理程序) 不幸的是,Javascript代理有一个“不变量”的概念,其中之一是: 应用于代理对象的[[GetPrototypeOf]]必须返回与应用于代理对象的目标对象的[[GetPrototypeOf

Javascript代理对象的一个应用程序是,通过将数据作为数组数组通过线路发送,同时使用一个对象列出每个字段的字段名和索引(即字段映射),从而减少网络流量。(而不是在每个对象中重复属性名称的对象数组)

乍一看,ES6代理似乎是在客户端使用数据的一种很好的方式(即以数组为目标,以字段映射为基础的处理程序)

不幸的是,Javascript代理有一个“不变量”的概念,其中之一是:

应用于代理对象的[[GetPrototypeOf]]必须返回与应用于代理对象的目标对象的[[GetPrototypeOf]]相同的值

换句话说,不可能使数组显示为对象(因为数组的原型与对象的原型不同)

解决方法是将包含字段/索引映射的对象作为目标,并将值嵌入代理处理程序中。这可以用,但感觉脏。它基本上与代理文档呈现的完全相反,它不是使用一个“处理程序”和许多“目标”,而是使用许多“处理程序”(每个处理程序都位于代理所表示的值数组的闭包中),所有处理程序共享同一个“目标”(即字段/索引映射)

“严格使用”;
类充气机{
构造函数(字段、值){
//通常,在“set”陷阱中还有额外的东西用于数据绑定、持久化等。
常量处理程序={
get:(fields,prop)=>value[(fields[prop]|{}).index],
集合:(字段,属性,值)=>value==(值[字段[prop].索引]=value),
};
返回新代理(字段、处理程序);
}
}
//这是服务器发送的内容
常量原始数据={
字段:{
col1:{index:0},//value是一个对象,因为通常有关于该字段的附加元数据
col2:{index:1},
col3:{index:2},
},
行:[
['r1c1','r1c2','r1c3'],
['r2c1','r2c2','r2c3'],
],
};
//在代理中循环和包装每个值应该非常便宜(内存和时间)
const data=rawData.rows.map((row)=>新充气机(rawData.fields,row));
//确认我们得到了我们想要的
assert(数据[0].col1==“r1c1”);
assert(数据[1].col3=='r2c3');
console.log(数据[0]);//这个输出是无用的(除了在堆栈溢出代码段控制台中,它似乎可以工作)
console.log(Object.assign({},数据[0]);//这个输出是有用的,但是必须跳过这个环很烦人
对于(数据[0]中的const prop]){//确认通过字段的循环工作正常
控制台日志(道具);

}
您省略了以下重要部分:

如果目标对象不可扩展,则应用于代理对象的[[GetPrototypeOf]]必须返回与应用于代理对象的目标对象的[[GetPrototypeOf]]相同的值

(我的重点)

如果数组数组是可扩展的(正常情况下),则可以从
getPrototypeOf
陷阱返回所需的任何对象(或
null
):

const data=[0,1,2];
const proxy=新代理(数据、{
getPrototypeOf(目标){
返回Object.prototype;
},
获取(目标、propName、接收者){
开关(propName){
案例“零”:
返回目标[0];
案例“一”:
返回目标[1];
案例“二”:
返回目标[2];
违约:
返回未定义;
}
}
});
console.log(Object.getPrototypeOf(proxy)==Object.prototype);//真的

console.log(proxy.two);//2
请每个问题问一个问题,而不是三个。至少,你上面的第三个问题应该与其他问题分开。第三个问题的上下文取决于问题1和2。如果代理正确地包装了一个目标(根据文档),那么在调试器中更容易看到值(因为它们是目标)。具体来说,当实现被反转(如上所述)时,在调试器中查看值会变得格外困难。但“为什么代理是这样的?”和“我如何改变代理在devtools中的显示方式?”是两个截然不同的问题。“通过将数据作为数组数组通过线路发送,以及列出每个字段的字段名和索引的对象来减少网络流量”-不,这不是JS代理的应用程序。您真的应该在您的服务器上启用。@Bergi是的,这里的方法首先是避免不必要的数据复制(而不是压缩数据)。话虽如此,在过去的一段时间里,我一直在考虑压缩它,但这对我来说并没有什么好结果()。感谢您的参考,我以前没有看到过这一点,在这种背景下阅读它是有意义的,因为它看起来像是一个基本的规则列表,这些规则是为了使语言内部一致而强制执行的。如果“Proxy”类只是一个javascript类,我可以理解为什么它必须遵循这些规则;但是,如果它是语言的一个基本特性,我希望它可以被豁免(但这可能是我不是语言开发人员的原因)。@Casey-:-)是的,即使是代理、数组、绑定函数等外来对象,也需要不变量。。。我知道在代理方面做了很多细致的工作(IIRC必须移除
enumerate
陷阱的原因与不变量的实现成本间接相关)。显然这很重要。我对上面的两个理由不满意,所以我得听听他的看法。(他在这方面很出色。)@Casey-我突然想起,你所考虑的限制只适用于目标对象不可扩展的情况。我已经更新了答案