jsPsych实验分支逻辑:基于被试响应的动态流程控制
在jsPsych 7 x中实现可靠的条件分支:彻底摆脱“提前读取数据”陷阱 在构建交互式心理学实验时,我们经常需要根据被试的实时选择来动态调整后续流程。最典型的场景就是**知情同意环节**——如果被试点击“同意”,则进入正式实验;如果选择“拒绝”,则显示结束语并退出。 这个需求看起来直截了当,但
知情同意书
本研究已通过伦理审查。您的参与完全自愿,有权在任何时候退出而无需承担任何后果...
`, 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`机制,你可以让实验流程真正“响应”被试的行为,而不是机械地执行预设脚本。 下次当你需要根据被试的选择来决定后续流程时,记住这个模式:先定义试验,再定义条件分支,让数据在正确的时机被读取。这样构建出来的实验,不仅更健壮,也更容易维护和调试。 毕竟,好的实验设计,应该像一场自然的对话——根据对方的回答,决定接下来要说什么。而你的代码,就是确保这场对话流畅进行的技术保障。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
用Object.getPrototypeOf动态检测前端灰度发布组件白名单
Object getPrototypeOf作为原型校验器,在白名单机制中验证组件实例的直接原型是否合法。白名单为构造函数prototype对象的强引用快照,需在第三方脚本前采集。校验失败后按灰度策略分级响应,并配合冻结原型链、拦截篡改入口等防御措施。
箭头函数在定时器中的应用实例
箭头函数在定时器回调中自动继承外层this,避免了传统函数this指向全局或undefined的问题,无需手动bind或保存闭包变量。但其无法改变this指向,且没有arguments对象,也不能用作构造器。使用时应理解词法作用域与执行上下文的区别。
JavaScript原型式继承写法与应用场景详解
原型式继承通过Object create()以现有对象为模板创建新对象,实现行为复用而非数据复制。适用于配置派生、游戏实体等轻量场景,但需注意引用类型共享、无法传参初始化及类型识别失效等限制。
JavaScript对象字面量writable属性的默认配置机制完全解析
对象字面量中属性描述符默认全部开启,writable为true可直接赋值修改;而Object defineProperty定义的属性,writable、configurable、enumerable均默认为false,需手动设为true才能修改或枚举。两者默认行为差异显著。
JavaScript浮点数比较布尔值逻辑错误避免方法
JavaScript浮点数采用IEEE754双精度标准,二进制存储导致小数运算精度损失,直接使用`==`或`===`比较常出现逻辑错误。通常引入容差比较,如`Math abs(a-b)
- 热门数据榜
相关攻略
2026-07-14 07:06
2026-07-14 07:06
2026-07-14 07:05
2026-07-14 07:05
2026-07-14 07:05
2026-07-14 07:05
2026-07-14 07:05
2026-07-14 07:04
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

