JavaScript cell
NotebooksObservable notebooks are often written in JavaScript cells, using the Web’s native language, but with a few changes. It’s helpful if you have some JavaScript experience, but don’t panic if you’re rusty or not an expert! Instead, try tinkering with the code to get a feel for how it works. Even the most wizened developer may yet learn by trial and error.
Expressions, variables & blocks
JavaScript cells can be for expressions, variable definitions or blocks of code. Expression cells are concise and are intended for simple definitions, such as basic arithmetic:
Variable definitions can be equal to an expression or a block of code.
Blocks of code are surrounded by curly braces {}
and are intended for more complex definitions, such as ones involving local variables or loops.
You can reference the output of a block of code by naming it:
Note
Any cell that you see with visible shading is pinned. This leaves the cell open so that the code is visible. A blue pushpin symbol appears in the left margin when you mouseover the cell.
Variables inside blocks are local to a cell
Local variables, like the x
seen in the block above, can’t be referenced from other cells; trying to reference an unknown variable results in a runtime error:
However, this error is localized to the broken cell the rest of the notebook is able to run and you are still able to access variables that are not inside blocks.
Object literals
Using curly braces is necessary not only when you are defining a block, but also when you are defining an object literal.
An object literal is an object with a set of name–value pairs that define properties of the object:
Notice the curly braces (like a block), but with parentheses surrounding the curly braces (unlike a block). If you want to define a cell as an object literal, you must wrap the literal in parentheses to disambiguate it from a block.
Functions
To repeat operations or share code between cells without copying and pasting, define a function:
This greet
function now can be called from other cells to display greetings:
Naming & referencing cells
While local variables are not visible across cell boundaries, you can name cells to reference their values.
You needn’t define named cells before you reference them: order your cells however you like, and Observable will automatically execute them in topological order. Out-of-order execution is especially helpful for improving the narrative flow of your notebook.
To rename a cell, you can edit it directly in the cell or within the cell toolbar:
Reactivity
A cell that references other cells is revaluated automatically whenever the referenced values change. In our example above where firstName
and lastName
were defined after fullName
, if we were to change the value of firstName
, then fullName
would update automatically without needed to be revaluated.
This reactivity is similar to live reload, with an important difference: when a value changes, only referencing cells are revaluated, rather than the entire notebook. This makes editing more responsive—notebooks update rapidly in response to changes—and you don’t lose independent transient state.
For example, the cell below computes a random walk in the cell randomWalk
, the next cell strokes a line, the shape of which is based on the value of the randomWalk
, and the third cell, stroke
, defines the color of the line. If you edit the stroke
cell, the random walk will change color, but the shape of the line remains the same. A new walk is only computed if you edit the randomWalk
cell.`
To understand reactivity, think of each cell as a function. For example, the cell sum = a + b
becomes a function that takes a
and b
as arguments, returning their sum; the runtime waits for the value of a
and b
to resolve and then invokes the sum
function. The runtime invokes sum
again whenever a
or b
change.
If a cell contains a yield
statement, the runtime creates a generator function instead of a normal function. Likewise if the definition uses await
, the runtime creates an async function. Reactivity greatly simplifies how you build user interfaces, script animations, and consume real-time data.