javascript - 保存对文档片段的引用的函数属性:何时使用 cloneNode?
问题描述
我无法理解对象的数据分配何时是引用以及何时创建对象的副本。我以为我理解了,但下面的例子不符合我对它的简单理解。
事件处理程序开始以下一系列步骤。
Promise.allSettled( [ gather_write, get_build ] ).then( test );
承诺gather_write
并get_build
执行不相关的功能。第一个从 DOM 收集一些数据并将其写入数据库。第二个从数据库中检索数据并构建文档片段。如果两者都满足,则 DOM 中的节点将替换为片段。
此处显示的代码太多,但是get_build
,在成功从数据库中获取数据后,调用一个单独的函数来构建文档片段,并将其结果作为解析对象的属性返回。效果很好;然后我想尝试在gather_write
拒绝和get_build
履行的情况下向用户提供选项,这需要临时存储文档片段。因此,与其将其返回并将其传递回 ,不如将其Promise.allSettled
存储在构建它的函数的属性中。
在同步函数build
中,代码设置为:
function build()
{
let f;
try
{
f = document.createFragment();
// ...build the fragment...
build.html = f;
}
catch(e)
{ }
finally
{ f = null; }
} // close build
函数build
必须在 promiseget_build
可以解决之前完成,之后Promise.allSettled
可以评估;build.html
并且,如果两个 promise 都满足,则可以调用将 DOM 节点替换为存储在其中的新建片段的函数。我认为这build.html
将是对节点对象的引用,f
并且由于f
在块中设置为 null finally
,这将在上述所有内容完成之前发生,并且当build.html
最终运行要使用的代码时,它将指向 null而不是片段。所以,赋值语句应该是build.html = f.cloneNode(true)
.
但是,无论是否使用f.cloneNode
. 你能解释一下为什么吗?如果没有必要,我不希望浏览器采取步骤克隆片段,但是在不理解为什么它在不克隆的情况下工作的情况下犹豫要排除它。
谢谢你。
解决方案
您可以将每个变量名视为指向内存位置的指针。将变量名设置为null
不会改变变量曾经包含的任何内容;它所做的只是将变量名指向的内容从先前的引用(此处为文档片段)更改为新的引用(null)。所以,当你这样做
f = document.createFragment();
build.html = f;
那么,无论f
将来是否/如何重新分配变量名称,build.html
都不会改变,因为它继续指向文档片段。改变的唯一方法是build.html
片段发生突变(例如f
在重新分配之前分配给 的属性,或调用片段的方法之一)。
这是此行为的另一个最小示例:
function foo() {
let f = { prop: 'val' };
foo.f = f;
f = null;
}
foo();
console.log(foo.f);
同样,在这里,虽然f
设置为null
,但该对象{ prop: 'val' }
保持完整且未变异,因此foo.f
获取对该对象的引用,并且即使在f
重新分配后仍继续持有该引用。
使用您的代码,由于内存中的片段保留在内存中,并且build.html
即使在重新分配后仍保留对该片段的引用f
,因此克隆片段只是不必要的开销;随意离开它。
另一种可视化方法是您的代码:
function build() {
let f;
try {
f = document.createFragment();
// ...build the fragment...
build.html = f;
} catch (e) {} finally {
f = null;
}
}
相当于
function build() {
let f;
try {
// Create the object in memory:
<MemRef#513513> = document.createFragment();
// Point the variable `f` to that created object:
f = <MemRef#513513>;
// ...build the fragment...
build.html = <MemRef#513513>;
} catch (e) {} finally {
f = <MemRef#Null>;
}
}
推荐阅读
- c# - c#中的猜数字游戏
- go - golang中映射的结构有多大?
- typescript - 用于对象导出和类型的 def 文件
- scikit-learn - 在scikit-learn Stochastic Gradient Descent分类器中,如何找到影响最大的自变量?
- python - 无法正确格式化 Python 中的输出
- visual-studio - 如何在 Visual Studio 2017 中禁用作为调试错误的失败断言?
- javascript - 在sails 中使用“basemodel”,从中派生并使用基类函数?
- google-colaboratory - 在 google colab 中保存 pip 安装
- python - 如何从所有键中仅提取某些项目?
- python - 将点的 GeoDataFrame 捕捉到单独的 GeoDataFrame 中的最近线