本文是一篇面向了解心理学实验设计基础,有一定的心理学实验开发能力和开发经验的朋友(比如已经使用过 E-Prime、PsychoPy、PsychToolBox 等实验框架)的快速上手指南。
本文不适合作为从零开始学习心理学实验的教程。如果你希望在未接触过心理学实验开发的情况下从零学习 jsPsych,请购买《jsPsych 从入门到精通》一书,或直接参考 jsPsych 的原始英文教程——它会写得更全面,面向那个上手也不会太慢。

0. 基本概念

回想一下你所学过的心理学实验的基本知识,以及你在 E-Prime、PsychoPy 等框架下创建实验的流程。心理学实验,尤其是行为实验中,最基本的要素是什么?

刺激-反应(stimulus-response)。你呈现一个刺激,被试对这个刺激作出对应的反应,随后你记录这个反应以及对应的各种数据。这样的一个最基本的 S-R 单元被称作试次(trial)。而一个完整的实验无非就是把多个 trial 以各种方式连接在一起。

如果你使用过 E-Prime、PsychoPy 这些图形化的实验程序编辑器,基本上能够体会到这套逻辑——在画面中构建一个个 trial 的组件,然后再以各种方式执行这些 trial,一个实验就出来了。

所以,jsPsych 也一样,只是 jsPsych 没有图形化的编辑器了——这意味着你需要手动用代码的形式来告诉 jsPsych,每一个 trial 长什么样,这些 trial 应该以什么样的方式来执行。

1. jsPsych 实验程序基本组成部分

这一段先摆在这里,作为一个必要的前置引入,但是初次看可能会很懵。没关系,你可以先跟着后面的操作来学,把后面的示例跑起来之后再结合着示例看看这一段,说不定就有更深入的理解了。

1.1 网页的基本组成

jsPsych 是一套直接基于网页的 JavaScript 实验程序框架。它不像 PsychoPy 衍生出的 PsychoJS 那样,通过内建的编辑器进行转换,而是直接面向网页进行编写和开发。优点在于,jsPsych 更灵活,你可以做出更多各种各样的东西,同时体积也更小巧;劣势当然是,你需要从头完整地写一个完整的网页出来,没人会帮你构建别的东西。这就要求你至少需要先了解网页的基本概念。

既然是直接面向网页进行开发,那么一个 jsPsych 的程序当然要拥有一个网页的基本要素了。正常来说,我们至少会需要如下几种文件:

- index.html (网页本体文件,告诉浏览器这个网页里有什么,应当加载什么内容)
- script.js (JavaScript 文件,一些可执行的代码,可以影响网页中的内容,也可以执行一些后台的操作)
- styles.css (CSS 文件,用来定义网页元素的样式,如大小、粗细、长宽、字体、字号等)

OK,别急,后面会一步一步讲的.jpg

1.2 jsPsych 程序的基本逻辑

聪明的你肯定已经猜到了,实验程序的本体一定是在那个 .js 的文件里面。我们的主要开发工作集中在编写实验用的 .js 程序中,再辅以对 .html.css 文件的编辑来实现整个流程。

jsPsych 的开发是高度模块化的——它的本体仅仅提供了一个框架,一个用来处理数据、提供交互接口、处理背景任务的框架。当你需要某种功能时,你需要先引入对应的插件,随后编写一段代码,告诉这个插件以什么样的参数、什么样的方式去运行。当你把所有需要运行的东西都定义好了之后,运行 jsPsych,它会按照你指定的顺序去读取各个模块的参数,然后显示在网页里,等待用户输入。

所以基本上,分三步走:

  1. 引入插件;
  2. 编写试次;
  3. 运行实验程序。

2. “不求甚解”——先写一个实验出来

本章节的实验示例改编自《jsPsych 从入门到精通》第七章所用的示例。

这一章会先教你如何创建一个 jsPsych 的实验。你需要根据下面的步骤一步步照做,但暂时不会涉及到具体的原理和机制。

这也是“不求甚解”的含义——先别问为什么,只要这样做,你就写出来了一个很简单的实验。它涉及到的原理和机制都将在后续讲解。

2.0 准备工作

对于平时不怎么接触一般普通编程的朋友来说,首先第一个问题就会困扰很久——我在哪里开始写呢?

答案是:没有“官方的”编辑器。你需要自己准备编辑器。

E-Prime 有自己的软件,PsychoPy 有自己的界面,但是 jsPsych 的本质就是一堆文本文件,不需要额外的编译工作——这意味着你拿记事本也能写。

当然我们不需要给自己上强度,如果你平时有涉猎编程的话,你的电脑里一定有一款代码编辑器或者 IDE 或者差不多的东西,用你最顺手的就行。如果你平时没接触过的话,这里推荐 Visual Studio Code(注意不是紫色的那个 Visual Studio,是蓝色的那个)。

右边那个,不是左边这个

下载,安装,然后打开。怎么配置 VS Code 是一门学问,这个主要看个人习惯,这里按下不表,各位可以自己搜索,自己配置。目前这个阶段只有一个推荐——如果你不习惯对着英文输出的话,在最左边的扩展菜单(Extensions)里面搜索 Simplified Chinese,安装简体中文扩展包。

在这里安装

2.1 创建文件夹,准备素材

找一个你顺手的地方,新建一个文件夹,命名为 simple_experiment。右键选择用 VS Code 打开这个文件夹,这个文件夹现在就成为了一个 VS Code 中的工作区。

创建文件和文件夹示例

点击这里,创建两个文件,一个叫 index.html,一个叫 default.css
再点击它旁边的新建文件夹,创建一个文件夹,叫 scripts
scripts 这个文件夹下新建一个文件,叫 exp.js

完成之后,它应该和上图的样子是一致的。

接下来,你需要两个素材文件,一个蓝色的圆形,一个橙色的圆形。你可以打开画图画一个,或者用下面的两个也行:

blue.png

orange.png

分别命名为blue.pngorange.png,在你的实验目录下新建一个文件夹images,把这两个文件放进去。

现在,你就准备好了所需的所有东西,整个目录看起来应该长这样:

实验目录文件结构

2.2 编辑 index.html

打开index.html,输入以下内容:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Experiment Demo</title>
</head>
<body>
</body>
</html>

这是网页文件的基本框架。
随后,在<head></head>标签之间,插入四行新的内容:

<script src="https://unpkg.com/jspsych@7.3.4"></script> <!--引入jsPsych框架-->
<script src="https://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.3"></script> <!--引入HTML插件-->
<link rel="stylesheet" href="https://unpkg.com/jspsych@7.3.4/css/jspsych.css"> <!--引入jsPsych基本样式表-->
<link rel="stylesheet" href="./default.css"> <!--引入自定义样式表-->

再在<body></body>之间,插入一行新的内容:

<script src="./scripts/exp.js"></script> <!--载入exp.js-->

2.3 编辑 exp.js

打开scripts/exp.js,首先写入第一行:

let jsPsych = initJsPsych();

然后,编写指导语:

// 指导语
let instruction = {
    type: jsPsychHtmlKeyboardResponse,
    stimulus: `
    <p>在实验中,屏幕中央会呈现一个圆形</p>
    <p>如果呈现的是蓝色圆形,请尽快按 F 键</p>
    <p>如果呈现的是橙色圆形,请尽快按 J 键</p>
    <p>按任意键开始实验</p>
    `,
    post_trial_gap: 500
}

然后,分别编写蓝色圆形和橙色圆形的试次:

// 蓝色圆
let blue_trial = {
    type: jsPsychHtmlKeyboardResponse,
    stimulus: `<img src="./images/blue.png">`,
    choices: ['f','j'],
    post_trial_gap: 500
}
// 橙色圆
let orange_trial = {
    type: jsPsychHtmlKeyboardResponse,
    stimulus: `<img src="./images/orange.png">`,
    choices: ['f','j'],
    post_trial_gap: 500
}

最后,编写执行试次的代码:

jsPsych.run([
    instruction,
    blue_trial, orange_trial, blue_trial, orange_trial, blue_trial, orange_trial
])

好了,程序写完了!保存一下,双击index.html运行试试看!

当然,这个程序所运行的仅仅只能从概念上被称作“实验”,距离能承担我们实际研究任务的实验程序还差得远,不过作为一个讲解,它是一个很好的例子,非常简单,非常易懂。我相信,在还没开始看下面的讲解之前,你就已经大概弄明白了上面的步骤分别是在做什么了。

3. “大概明白”——来讲讲刚刚我们都做了什么

3.1 index.html

再看看刚刚我们写好的index.html里都有什么:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Experiment Demo</title>
    <script src="https://unpkg.com/jspsych@7.3.4"></script> <!--引入jsPsych框架-->
    <script src="https://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.3"></script> <!--引入HTML插件-->
    <link rel="stylesheet" href="https://unpkg.com/jspsych@7.3.4/css/jspsych.css"> <!--引入jsPsych基本样式表-->
    <link rel="stylesheet" href="./default.css"> <!--引入自定义样式表-->
</head>
<body>
    <script src="./scripts/exp.js"></script> <!--载入exp.js-->
</body>
</html>

当浏览器访问任何一个网站时,通常情况下,它会读取到这样一个 HTML 的文档,并按照这个文档的指示来加载网页的基本内容

我们第一步写入的部分(没有带注释的部分)是网页文件的基本框架。<head></head>包裹的部分是网页的“头数据”。这里包括了两个部分

  • 一些基本的信息(字符集、网页宽度、网页标题,这些对我们实验本身不是很重要);
  • 一些需要在网页本体内容开始加载前就要载入的东西,比如我们加入的这些<script><link>

<body></body>里的内容则是网页本身要显示的内容。

在这里,我们告诉浏览器,在具体的内容(<body>)开始加载前,首先加载必要的依赖项——jsPsych 框架本体和样式表,我们所需要的 jsPsych 插件(plugin-html-keyboard-response),我们自己的样式表。

随后,网页开始加载<body>里的内容,而我们在这里放上了我们的实验文件——exp.js

3.2 exp.js

let jsPsych = initJsPsych();

let instruction = {
    type: jsPsychHtmlKeyboardResponse,
    stimulus: `
    <p>在实验中,屏幕中央会呈现一个圆形</p>
    <p>如果呈现的是蓝色圆形,请尽快按 F 键</p>
    <p>如果呈现的是橙色圆形,请尽快按 J 键</p>
    <p>按任意键开始实验</p>
    `,
    post_trial_gap: 500
}

let blue_trial = {
    type: jsPsychHtmlKeyboardResponse,
    stimulus: `<img src="./images/blue.png">`,
    choices: ['f','j'],
    post_trial_gap: 500
}

let orange_trial = {
    type: jsPsychHtmlKeyboardResponse,
    stimulus: `<img src="./images/orange.png">`,
    choices: ['f','j'],
    post_trial_gap: 500
}

jsPsych.run([
    instruction,
    blue_trial, orange_trial, blue_trial, orange_trial, blue_trial, orange_trial
])

首先,我们在这个文件的最开头初始化了 jsPsych 框架。

随后,我们定义了三个试次:一个用于呈现指导语,一个用于呈现蓝色圆形刺激,一个用于呈现橙色圆形刺激。这三个试次的类型(type)都是jsPsychHtmlKeyboardResponse,与我们在前面index.html中引入的插件一致。

在 jsPsych 中,任何试次的呈现都必须依赖插件,因此我们必须先引入这个插件,然后在实验程序中使用与这个插件对应的type参数。

然后,我们通过stimulus参数告诉实验程序,在这个试次中应该呈现什么内容,再通过choices参数告诉程序要接受哪些按键作为反应——当这个参数为空时,按下任意键均可以接受;当这个参数不为空时,只有这个参数指定的按键才会触发反应。

post_trial_gap这个参数,则指定了本次试次后,呈现多长时间的空屏,单位为毫秒。你可以把这个参数改为10002000,自己试试效果。

最后,我们执行了一个函数:jsPsych.run()。这个函数接受一个数组,按照数组的顺序来执行定义好的试次。在这里,我们让它首先呈现指导语试次,然后呈现蓝橙刺激各 3 次。

所以,jsPsych 程序的编写,主要集中在如何定义每一个试次,以及如何安排试次运行两个方面。

4. 小结与习题

在这篇文章中,你已经大概知道了 jsPsych 程序要如何编写了。首先,准备好所有的素材,然后编写网页文件和实验程序文件,在实验程序文件中定义好需要做的试次,最后执行。

作为一个入门的教程,这篇文章先讲到这里。后面我们将基于这个示例,继续打磨这个程序,把它打磨成一个完整的,可以应用的实验程序。

学习 jsPsych 一定需要你接触各种各样的网页开发知识,因此这里提出数个问题,留作习题,大家可以在完成这些习题的过程中逐步理解它背后的原理。

习题 1

在本文的示例中,我们使用了 jsPsych 的 html-keyboard-Response 插件来呈现各个试次。你能否用 image-keyboard-response (一个仅接受图片文件作为刺激的插件)来重写这个程序呢?

习题 2

你能否更改网页的背景颜色为黑色,文字颜色为白色呢?

  • 你需要学习的:CSS 的编辑

    • 不要被庞大的教程体系吓坏了,你只需要看和“背景”“文字”有关的部分就可以了!
    • 你也可以使用搜索引擎或生成式人工智能来教你如何完成这个任务。

习题 3

我们运行实验的方式相当笨拙,手动把每个试次重复了三次。能否用别的方式(比如循环?)来简化这个过程呢?

  • 你需要学习的:jsPsych 的 Timeline

    • 这也是下篇教程的重点,因此一时半会没看太明白也不用担心。

习题 4(较难)

你能否不使用图片文件完成这个实验程序呢?

  • 你需要学习的:如何使用 CSS 画圆

    • 完成这个任务需要你对 HTML 和 CSS 有相当程度的了解。
最后修改:2024 年 04 月 24 日
虽然点赞什么的确实没什么意义但是也可以点一个再走呗?(