We have to claim variables in advance?

Interestingly, if I claim variable like

function setup() {
  createCanvas(100,100);
  let pg = createGraphics(100,100);  // claim variable like this
}

function draw() {
  pg.background(100);
  image(pg, 0, 0);
}

when I call pg.background(100), the error occurs “pg is not defined”.

But if I claim it in advance like

let pg;

function setup() {
  createCanvas(100,100);
  pg = createGraphics(100,100);  // claim variable like this
}

function draw() {
  pg.background(100);
  image(pg, 0, 0);
}

it works.

You know these two claim methods are both right in Javascript, but one fails in p5.js, why? after all javascript is the foundation of p5.js。

So we must claim variables in advance?

2 Likes

Variables declared inside a function are local to that function and cease to exist once that function returns; unless they also become closures. :nerd_face:

Alternatively you can opt to turn a variable into a global property instead, via window or globalThis: :globe_with_meridians:
developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis
let pg = createGraphics(100, 100); —> globalThis.pg = createGraphics(100, 100);

3 Likes

Hello,

See:
Variable Scope

You are using the term “claim variables”; I am not familiar with this in this context.

I am familiar with “declare variables”.

:)

1 Like

also a funny thing is that this works too


function setup() {
  createCanvas(100,100);
  pg = createGraphics(100,100);  // claim variable like this
}

function draw() {
  pg.background(100);
  image(pg, 0, 0);
}

let pg;

as written above, it’s about the scope and not necessarily “in advance”.

2 Likes

The code that @micuat posted here works because the setup() and draw() functions get defined, but do not actually get called, until after pg gets declared, because the statement that declares pg is in the outer scope, even though it is situated below the code that defines the functions.

We can display output to observe the order of execution, as follows:

function setup() {
  createCanvas(100,100);
  pg = createGraphics(100,100);  // claim variable like this
  console.log("setup() was called.");
  noLoop();
}

function draw() {
  pg.background(100);
  image(pg, 0, 0);
  console.log("draw() was called.");
}

let pg = "I declare pg, and execute before setup() and draw() are called().";
console.log(pg);

Output:

I declare pg, and execute before setup() and draw() are called().
setup() was called.
draw() was called.

EDITED on April 17, 2021 to revise the output statements slightly.

1 Like

Also be careful because there’s the concept of hoisting in JavaScript :

Conceptually, for example, a strict definition of hoisting suggests that variable and function declarations are physically moved to the top of your code, but this is not in fact what happens. Instead, the variable and function declarations are put into memory during the compile phase, but stay exactly where you typed them in your code.

And the example:

JavaScript only hoists declarations, not initializations. If a variable is declared and initialized after using it, the value will be undefined. For example:

console.log(num); // Returns undefined, as only declaration was hoisted, no initialization has happened at this stage
var num; // Declaration
num = 6; // Initialization

It means you can reference a variable that is declared later in your code because its declaration is moved to the top of the program. The initialization itself is at the same place in your code :wink:

In other languages, it gives you an error like variable xxx was not declared in this scope…

2 Likes

The following experiment was performed with the Processing Development Environment and the Chrome browser.

So as to focus on the declaration, and leave the issue of assignment of a value to the variable out of the picture for now, let’s try this:

function sycamore() {
  console.log(tree);
}
let tree; // variable declared prior to function call
sycamore();

The JavaScript console displayed:

undefined

Now let’s do this:

function sycamore() {
  console.log(tree);
}

sycamore();
let tree; // variable declared after the function call

The JavaScript console displayed:

Uncaught ReferenceError: Cannot access 'tree' before initialization
at sycamore (p5js-temp-p5js_2021_04_17a5267812242042862675.js:2)
at p5js-temp-p5js_2021_04_17a5267812242042862675.js:5

So, at least in the environment where this experiment was performed, it did matter where in the global scope the variable was declared.

EDITED (April 17, 2021) to adjust the wording of the final paragraph.

1 Like