知情同意书
本研究已通过伦理审查。您的参与完全自愿,有权在任何时候退出而无需承担任何后果...
`, choices: ['我自愿同意参与本研究', '我不同意参与本研究'], data: { task: 'consent' }, on_finish: function(data) { // 可选:添加明确的标记,便于后续调试 data.consented = (data.response === 0); // 左按钮索引为0表示“同意” } }; // 2. 定义两个可能的分支内容 const instr_Consented = { type: jsPsychHtmlKeyboardResponse, stimulus: `感谢您的同意!
接下来将开始正式实验任务。请仔细阅读后续说明。
`, choices: [' '], // 空格键继续 data: { task: 'post_consent' } }; const instr_NotConsented = { type: jsPsychHtmlKeyboardResponse, stimulus: `我们尊重您的决定
实验到此结束。感谢您抽出时间考虑参与本研究。
`, choices: [' '], data: { task: 'exit' } }; // 3. 创建带条件判断的时间线节点(关键步骤!) const consented_branch = { timeline: [instr_Consented], conditional_function: function() { // ✅ 安全获取:通过task标签精确筛选,而非依赖顺序索引 const consent_data = jsPsych.data.get().filter({task: 'consent'}).last(); return consent_data && consent_data.response === 0; } }; const not_consented_branch = { timeline: [instr_NotConsented], conditional_function: function() { const consent_data = jsPsych.data.get().filter({task: 'consent'}).last(); return consent_data && consent_data.response === 1; // 右按钮索引为1 } }; // 4. 构建主时间线 const timeline = [consent, consented_branch, not_consented_branch]; // 5. 启动实验 jsPsych.run(timeline); ``` ## 关键要点与最佳实践 ### 避免`last(1)`硬索引依赖 在简单线性流程中,`last(1)`或许能侥幸工作。但一旦实验复杂起来——比如包含循环、嵌套时间线、并行流程——试验的执行顺序就可能与代码中的书写顺序不一致。`last(1)`获取的未必是你想要的那次试验。 **正确做法**:始终使用`filter()`方法,通过明确的`data`属性(如`{task: 'consent'}`)来精确定位目标试验。这样无论该试验在时间线的哪个位置执行,你都能准确找到它。 ### `conditional_function`必须返回布尔值 这个函数只有一个任务:返回`true`或`false`。如果返回`true`,则执行该节点下的`timeline`;如果返回`false`,则跳过整个节点。 注意逻辑的严谨性。比如上例中,我们明确检查`response === 0`而不是`== '0'`,避免JavaScript类型转换可能带来的意外结果。 ### 理解执行时机 `conditional_function`的调用时机很巧妙:**正好在该节点即将渲染之前**。这意味着,当系统判断是否要显示`consented_branch`时,前面的`consent`试验肯定已经执行完毕,其数据已经写入`jsPsych.data`中,可以安全读取。 这种“按需判断”的机制,正是解决“提前读取”问题的核心。 ### 扩展应用场景 掌握了条件时间线的基本模式后,你可以实现更复杂的分支逻辑: - **多级分支**:同意参与后,再根据人口学问卷的结果(如性别、年龄组)分配不同的实验版本 - **动态跳转**:根据被试在练习环节的表现,决定是否提供额外指导或直接进入正式实验 - **自适应流程**:基于实时计算的任务表现,动态调整后续任务的难度或数量 对于更复杂的分组需求,可以结合`jsPsych.timelineVariable`和`sample`插件,实现随机化分配或平衡设计。 ## 总结 条件分支不是jsPsych的进阶功能,而是构建任何非 trivial 实验的**基础能力**。通过`conditional_function`机制,你可以让实验流程真正“响应”被试的行为,而不是机械地执行预设脚本。 下次当你需要根据被试的选择来决定后续流程时,记住这个模式:先定义试验,再定义条件分支,让数据在正确的时机被读取。这样构建出来的实验,不仅更健壮,也更容易维护和调试。 毕竟,好的实验设计,应该像一场自然的对话——根据对方的回答,决定接下来要说什么。而你的代码,就是确保这场对话流畅进行的技术保障。