我对JSON.stringify的序列化步骤与将对象写入indexedDB中的对象存储区之间的浏览器/ CPU /内存效率方面的差异感兴趣。
问题的动机或背景是以最有效的方式将数据库中的对象写入客户端的硬盘驱动器。为此,使用get语句检索对象并将其写入对象,该对象将转换为带有JSON.stringify的字符串,然后将其作为文本写入磁盘。我假设get语句从数据库中的序列化形式反序列化对象。如果是这样,那么该对象将从indexedDB表单中反序列化,然后序列化为JSON.stringify形式。
然后,要从磁盘恢复数据,将读取文件,将文本转换为具有JSON.parse的对象,并将对象添加或放入数据库,这似乎需要另一个序列化步骤。因此,JSON字符串被解析为一个对象,然后序列化为indexedDB表单。
我的问题的第一部分是可以以序列化形式从数据库中检索对象,以便可以以相同的形式将其保存到磁盘,并再次写入数据库,而无需执行stringify /的中间步骤解析?
问题的第二部分是,如果不可能这样做,并且对于使用indexedDB而没有任何索引并且从不以除了外部唯一键之外的任何值查询数据的特殊情况,将字符串化对象存储到数据库而不是对象有什么好处吗?
在这种情况下,写入/读取磁盘不会涉及中间的字符串化/解析步骤,并且当字符串在数据库中获取/放入时不存在反序列化/序列化步骤,因为它不是对象。但是,要更改数据库中这些字符串之一的值,需要在get的结果上使用JSON.parse将其转换为对象,然后在将字符串放回之前更改值后再使用JSON.stringify数据库中。
但是当使用get和put对象时,JSON.parse和JSON.stringify如何与数据库对象的反序列化和重新序列化相比较?我认为将对象序列化为indexedDB需要的不仅仅是JSON.stringify,因为前者可以通过其属性进行查询。
我将试验看是否可以观察到差异,但是如果存在潜在原因(在这种情况下,使用一种方法而不是另一种方法),则想要询问了解两种类型序列化的内部工作原理的人。 / p>
修改
显然,如果我理解正确,结构化克隆算法用于在indexedDB中存储对象;但是这个结果在存储之前仍然是序列化的吗?和JSON使用词法语法但从不复制对象。
也许,我只是非常困惑,并且没有写入indexedDB的序列化步骤,并且我观察到的RAM的使用增加是克隆对象,然后将对象存储为对象。如果是这样,那么问题的第一部分根本没有意义,因为数据库对象总是需要转换为字符串以保存到磁盘。我的问题的第二部分将变得对浏览器要求更高,1)将对象转换为字符串或克隆它; 2)从数据库检索和对象与检索字符串(如果保存为JSON字符串)并解析它?
在找到关于此的更多信息后,虽然其中很多都是我的头脑,但我不确定这个问题是否值得考虑。
谢谢。
答案 0 :(得分:2)
将对象转换为字符串并在数据库中存储字符串没有性能优势。仅使用JSON.stringify 将对象转换为字符串会增加必须执行的步骤数。我强烈建议不要这样做,甚至不要尝试这样做,也不要试图超越C ++中的indexedDB实现。
indexedDB序列化发生在C ++中,而不是js。 JSON.stringify发生在js中,而不是C ++中。大多数情况下,js中发生的任何事情都比C ++慢几个数量级。
js字符串是js对象。如果我没记错,你不能将字符串存储为indexedDB中的对象,因为它本身是一个函数对象,而不是普通对象。说明这一点的另一种方法是考虑对象类型层次结构。一切都从Object
延伸出来。 Function
从对象延伸。 String
从Function
延伸(嗯,也许不是直接或明确,但仍然有效)。从Function
延伸的任何后代,例如使用class Foo
或function Foo() {}; new Foo();
或new Function('foo');
创建的任何后代,都不可序列化。从Object
延伸而不从Function
延伸的任何内容都是可序列化的。
函数不可序列化,如我对您的其他问题的回答中所述。
使用 object literal 语法创建js对象时,这仅仅是new Object()
的语法糖,而不是function Foo()
。这些对象很容易序列化,因为它们基本上只是字典。也就是说,直到您附加方法为止。一个方法再次只不过是一个绑定为对象属性的函数。因为即使是具有至少一种方法的普通对象也不再可序列化。
您可以只将字符串存储为非函数对象的其他对象的属性,而不是尝试将字符串直接存储在indexedDB中,因为它本身就是一个对象(Function
的后代),因为indexedDB已经明确了解String类型,并明确声明支持使用字符串值存储对象属性,因为它知道如何在序列化期间强制这些值。
结构化克隆算法在不久前重命名。它现在是序列化算法或类似“可转移”算法的东西,我忘了。
当你在indexedDB中存储一个对象(例如{x:1,y:2}
)时,它将从JS发送到C ++,然后在C ++中它将被序列化。当您从indexedDB中检索对象时,在C ++中它将以串行形式找到对象,对其进行反序列化,然后将其传递给JS,然后JS将其传递给您(您的函数或返回值)。虽然序列化更具体地指的是将另一种类型转换为字符串,但您也可以更一般地使用它来指向两个方向,因此请记住,技术文档中任何地方提到的序列化可能实际上是在谈论反序列化。
此C ++序列化不一定是从对象到字符串或字符串到对象,而是从一些优化的字节格式。在C ++领域,区分字符串和其他值类型有时没那么有用,因为字符串只是字节的任意表示。因此,当我们谈论C ++中的序列化时,我们只是在谈论改变抽象字节组的表示。就像C中的结构只是表示分成部分的字节序列一样。从某种意义上说,在C ++中,字符串可以理解为零成本抽象,具体取决于它的使用方式。实际上,调用一些字节组的类型或其他类型实际上只是用于阐明应该在这些字节上调用哪些操作,以及这些字节应该是什么意思。在某种意义上,这里的序列化实际上可能只是通过不同的名称调用相同的字节序列,而根本不执行任何处理!事实上,如果您曾经在文本编辑器中打开过二进制文件,或者打开了错误编码(或编码解释)网页,您可能已经目睹了这一点。因此,如果你在谈论不同的性能,那么,将0步操作与n步操作进行比较会产生明显的答案。
也就是说,C ++序列化可能具有讽刺意味的是最终转换为字符串,谁知道,你不应该知道,由indexedDB C ++实现决定这一点并将它从你身上抽象出来并隐藏它的复杂性。有效存储大量字节的所有类型的其他问题都远远超出了序列化性能。
总而言之,序列化在C ++中的含义与JSON中JSON.stringify的含义不同。在js中将值转换为字符串只会降低程序的速度。让indexedDB为您解决这个问题。