Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/441.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.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
将具有循环引用的对象从服务器传递到客户端Javascript,同时保持循环性_Javascript_Node.js_Express_Pug_Circular Reference - Fatal编程技术网

将具有循环引用的对象从服务器传递到客户端Javascript,同时保持循环性

将具有循环引用的对象从服务器传递到客户端Javascript,同时保持循环性,javascript,node.js,express,pug,circular-reference,Javascript,Node.js,Express,Pug,Circular Reference,我正在尝试将一个具有循环引用的对象从node.js服务器传递到客户端javascript 服务器(node.js): 客户端Jade/Javascript script var object = !{JSON.stringify(object)}; 这里我得到一个错误,object包含循环引用 使用 循环引用?道格拉斯·克罗克福德(Douglas Crockford)对此有一个解决方案,我曾经成功地用它解决过这个问题: 不要只使用stringify和parse,而是首先调用decycle并使用

我正在尝试将一个具有循环引用的对象从node.js服务器传递到客户端javascript

服务器(node.js):

客户端Jade/Javascript

script var object = !{JSON.stringify(object)};
这里我得到一个错误,
object
包含循环引用

使用
循环引用?

道格拉斯·克罗克福德(Douglas Crockford)对此有一个解决方案,我曾经成功地用它解决过这个问题:

不要只使用
stringify
parse
,而是首先调用
decycle
并使用
retrocycle

var jsonString = JSON.stringify(JSON.decycle(parent));
var restoredObject = JSON.retrocycle(JSON.parse(jsonString));

我推荐我的西伯利亚套餐,该套餐已上市

首先,我将通过示例说明该算法。下面是我们的示例数据结构(Joe喜欢苹果和桔子,而Jane喜欢苹果和梨。)

var-Joe={name:'Joe'};
var Jane={name:'Jane'};
var Apple={name:'Apple'};
var Orange={name:'Orange'};
var Pear={name:'Pear'};
函数addlike(人、水果){
person.likes=person.likes | |[];
fruit.likedBy=fruit.likedBy | |[];
人。喜欢。推(水果);
水果。喜欢。推(人);
}
addlike(乔,苹果);addlike(乔,橙色);
阿迪利克(简,苹果);addlike(简,梨);
var myData={人:[乔,简],水果:[苹果,橘子,梨]};
这为我们提供了以下对象图(根对象myData是树冠位于左中的树)

为了序列化,我们必须找到一种以非循环方式对对象图中包含的信息进行编码的方法

当我们通过对根对象应用递归的
discover
函数来确定对象图时(
discover
本质上是深度优先搜索,对已经看到的对象添加了停止条件),我们可以轻松地“计数”对象图的节点(对象),即用连续整数标记它们,从零开始(零始终是根的标签)。然后我们还将“计算”遇到的非对象(或“原子”);他们将得到负整数作为标签。在我们的示例中,所有原子都是字符串。[更一般的示例将包含其他原子类型,例如数字和“准原子对象”,例如正则表达式或日期对象(JavaScript内置对象具有字符串化的标准方式)]。例如,pear得到数字8只是因为它是我们的搜索算法发现的第8个对象。这是添加了整数标签的对象图

使用整数标签,序列化很容易。每个对象的“冻结版本”是一个具有相同键的对象,但每个值都被某个整数替换。每个整数都是某个表的索引;对象表,如果是负数,则为原子表

下面是我们示例的对象表

原子表呢

例如,pear对象的冻结版本(具有
.name=“pear”
.likedBy
=包含Jane的数组)是对象
{name:-4,likedBy:9}
,因为原子表在插槽4中有字符串“pear”,而对象表在插槽9中有包含Jane的数组

序列化算法的一个稍微简化的版本(即,除了处理原子类型之外,它什么都做;特别是,它适用于我们的示例数据结构)只有32行代码,如下所示:

函数forestify\u aka\u decycle(根){
var objects=[],inverseObjects=new WeakMap(),forest=[];
var atomics={},atomicCounter=0;
功能发现(obj){
var currentIdx=objects.length;
反演对象集(obj,currentIdx);
对象。推送(obj);
林[currentIdx]=Array.isArray(obj)?[]:{};
Object.keys(obj).forEach(函数(key){
var val=obj[key],type=typeof val;
if((type=='object')&&(val!==null)){
如果(inverseObjects.has(val)){//已知对象已具有索引
林[currentIdx][key]=inverseObjects.get(val);
}else{//未知对象,必须递归
林[currentIdx][key]=discover(val);
}
}否则{
if(!(原子中的val)){
++atomicCounter;//原子表新条目
原子[val]=原子计数器;
}
林[currentIdx][key]=-atomics[val];//rhs负
}
});
返回电流Idx;
}
发现(根);
返回{
目标:森林,
原子表:[null].concat(对象.键(原子))
};
}
objects表是一个数组,在每个插槽中包含一个简单的键值对列表(具有深度1树),它被称为forest,也就是名称。 由于森林中的树木被冻结,“西伯利亚”被选为算法的名称

相反的过程(
unfestify
aka retrocycle)更加简单:首先,为林中的每棵树生成一个空数组或一个空的普通对象。然后,在森林的树和树的键的双循环中,做一个明显的赋值,右边是我们正在构建的解冻森林中的“解冻”树,或者是从atmoics表中获取的原子

功能森林(森林化){
var ThawedObject=[];
var objectsTable=forestified.objectsTable;
var atomsTable=forestified.atomsTable;
变量i,输入,解冻,键,j,键,frozVal;
对于(i=0;i 1->2->3->4->5->6->7->8。我们遇到了对象根->所有人->乔->乔斯水果->苹果->苹果树->苹果树->简->珍妮丝水果->梨
var jsonString = JSON.stringify(JSON.decycle(parent));
var restoredObject = JSON.retrocycle(JSON.parse(jsonString));