Common pitfalls developing JavaScript applications in R
The examples below use the following options
debug = TRUE, rules = basic_rules(), deparsers = basic_deparsers(), asset_tags = basic_tags()
in the source_r
function call. Under this setting, R functions are not
loaded into the environment.
1. JavaScript uses 0-based indexing
x <- Array(1, 2, 3) # Array is a function provided in JavaScript
console::log(x[0])
2. Undeclared variables are created in the global environment
f <- function() {
x <- 3 # Variable used without declaration
return(x)
}
console::log(f())
console::log(x) # 'x' shows up in the global!
While directly accessing and modifying global variables are not uncommon
in JavaScript visualisations - as we will see when we use p5.js
in the
other articles - it is best to use it only when it is necessary. Here is
how one declares a variable before using it:
f <- function() {
declare(x) # Declare variable. Alternatively, you can combine
x <- 3 # the two lines using `let(x = 3)`.
return(x)
}
# console::log(x) # This will throw an error.
3. return
in JavaScript function must be explicit
add <- function(x, y) {
x + y # returns nothing, i.e. undefined
}
console::log(add(3, 4)) # expects nothing
add2 <- function(x, y) {
return(x + y) # returns x + y
}
console::log(add2(3, 4)) # expects 7
4. JavaScript function reads argument by position / order
first <- function(x, y) {
return(x)
}
console::log(first(y = 3, x = 1)) # the result is 3, not 1!
Note that since JavaScript does not use named argument, y = 3
and x
= 1
are actually interpreted as assignments! Both assignments will
happen before the function first
is called.
But don’t worry, this won’t be a problem in sketch
as it will strip
off all the names during the transpilation, i.e. first(y = 3, x = 1)
gets transpiled into first(3, 1)
. The design decision rules out the
use of in-place assignments, but it guards against unintended ones.
5. JavaScript passes objects by reference (think of R6
in R)
x = Array(1, 2, 3)
y = x
z = Array(...x) # make a copy explicitly
y[0] = 999
console::log(x) # x is modified!
console::log(y)
console::log(z)
6. A browser session has a pre-populated namespace
For example, the variables document
, window
, location
, var
,
stop
, open
, focus
are taken already. Avoid assigning values to
these variables!
The full list can be found with the following code:
# The object (strictly) named "window" refers to your browser window
for (b in Object::keys(window)) {
if (window$hasOwnProperty(b)) console::log(b)
}