函数范围 "lock" 是否是针对异步事件和快速连续函数调用所做的更改的值?
Does function scope "lock" a value against changes made in asynchronous events and rapid successive function invocations?
在网页的一部分中,通过单选按钮、复选框和输入元素集提供用户选项,并且更改事件侦听器放置在包含所有选项的父级上。
更改事件处理程序构建 undo/redo 选项选择所需的信息对象,将最近的更改作为函数 属性 推送到 RAM,将其写入 indexedDB,然后,在写入请求的事务 oncomplete 处理程序,根据作为函数 属性 写入 RAM 的数据,记录对文档区域更改的描述,供用户查看。
如果用户编辑 input 元素中的值并在它仍然具有焦点时单击单选按钮,则会触发两个更改事件,每个事件都会调用父事件侦听器的相同处理函数。
写入RAM和indexedDB的数据被准确记录,但是如果用户快速执行点击,第二个更改事件在第一个更改事件的写入事务完成之前再次更新函数属性,这样当第一个事件的日志描述是根据该函数 属性 中保存的最新选择构建的,它使用第二个事件的数据,导致两次记录到第二个事件选择的 DOM。
为防止这种情况发生,选项选择对象的独立副本在生成后立即分配给在更改事件处理函数中本地声明的变量。它似乎在工作,因为无论我尝试多快地尝试单击单选按钮,同时带有编辑的输入元素保持焦点,我都无法重现之前发生的事情。
我的问题是,制作撤消对象的副本是否保证 oncomplete 处理程序将始终引用该局部函数变量来构建日志,即使第二个更改事件更新了函数 属性在 oncomplete 事件触发之前,它被复制并制作了一个新副本?该局部函数的变量值是否“锁定”在函数范围内,以便它的第二次调用不能改变第一次调用的 oncomplete 事件用于构建日志的内容?
谢谢。
阅读@Bergi 的回答后,他对“共享对象”的使用让我明白了一些事情,因为我的术语很糟糕。
由于共享对象是一个对象数组,其中每个对象都是 undo/redo 所需的数据,每个更改事件都需要修改共享对象,因此数据存在于潜在 undo/redo 中。问题不在于第二个事件正在添加到数组中,而第一个事件的数据库写入完成并且在它引用数组中的最后一个元素以构建日志项之前。问题是日志项总是引用数组中的最后一个对象。 undo 对象不需要克隆(因为它在 RAM 中作为函数 属性);相反,当两个变化事件快速连续发生时,数组索引需要存储在局部变量中以供参考,以便从最后一个元素或倒数第二个元素构建日志。
是的。每个函数调用都会创建自己的局部变量,并且其范围之外的任何代码都无法访问它们。在您的场景中,您还必须注意不要修改共享对象,而是克隆它们。
在网页的一部分中,通过单选按钮、复选框和输入元素集提供用户选项,并且更改事件侦听器放置在包含所有选项的父级上。
更改事件处理程序构建 undo/redo 选项选择所需的信息对象,将最近的更改作为函数 属性 推送到 RAM,将其写入 indexedDB,然后,在写入请求的事务 oncomplete 处理程序,根据作为函数 属性 写入 RAM 的数据,记录对文档区域更改的描述,供用户查看。
如果用户编辑 input 元素中的值并在它仍然具有焦点时单击单选按钮,则会触发两个更改事件,每个事件都会调用父事件侦听器的相同处理函数。
写入RAM和indexedDB的数据被准确记录,但是如果用户快速执行点击,第二个更改事件在第一个更改事件的写入事务完成之前再次更新函数属性,这样当第一个事件的日志描述是根据该函数 属性 中保存的最新选择构建的,它使用第二个事件的数据,导致两次记录到第二个事件选择的 DOM。
为防止这种情况发生,选项选择对象的独立副本在生成后立即分配给在更改事件处理函数中本地声明的变量。它似乎在工作,因为无论我尝试多快地尝试单击单选按钮,同时带有编辑的输入元素保持焦点,我都无法重现之前发生的事情。
我的问题是,制作撤消对象的副本是否保证 oncomplete 处理程序将始终引用该局部函数变量来构建日志,即使第二个更改事件更新了函数 属性在 oncomplete 事件触发之前,它被复制并制作了一个新副本?该局部函数的变量值是否“锁定”在函数范围内,以便它的第二次调用不能改变第一次调用的 oncomplete 事件用于构建日志的内容?
谢谢。
阅读@Bergi 的回答后,他对“共享对象”的使用让我明白了一些事情,因为我的术语很糟糕。
由于共享对象是一个对象数组,其中每个对象都是 undo/redo 所需的数据,每个更改事件都需要修改共享对象,因此数据存在于潜在 undo/redo 中。问题不在于第二个事件正在添加到数组中,而第一个事件的数据库写入完成并且在它引用数组中的最后一个元素以构建日志项之前。问题是日志项总是引用数组中的最后一个对象。 undo 对象不需要克隆(因为它在 RAM 中作为函数 属性);相反,当两个变化事件快速连续发生时,数组索引需要存储在局部变量中以供参考,以便从最后一个元素或倒数第二个元素构建日志。
是的。每个函数调用都会创建自己的局部变量,并且其范围之外的任何代码都无法访问它们。在您的场景中,您还必须注意不要修改共享对象,而是克隆它们。