by Feiyue Zhang (2025)
I collected some common concept, confusion, and tips while coding in JavaScript.
This page might be helpful if you are already experienced in coding and would like to quickly get the hang of JavaScript!
There are 3 declaration keywords in JavaScript to declare variables.
const declares a constant; its reference cannot be reassigned, but if it holds an object or array, the contents can still be modified:
const x = 1; x = 2; ❌
const person = { name: "Alice" }; person.name = "Bob"; ✅
Both let and var declare a variable:
Variables declared through let are only defined in the block-scope:
function example() {
if ( true ) { var x = 10; let y = 20; }
console.log( x ); // 10 (var is function-scoped)
console.log( y ); // ❌ ReferenceError
}
Variables declared through var are initialized as undefined → unsafe
Accessing an undefined value does not throw an error, as it just quietly gives you undefined
There's something called "hoisting" if you're interested in why it's unsafe
TL;DR - don't use var
You don't need to specify the type of parameters in JavaScript functions:
function add( a, b ) {
return a + b;
}
And you can pass in anything:
add( 1, 2 );
add( "john", "doe" );
You can set default parameter, which will be replaced with your assigned value when the argument is missing or undefined:
function print( name = "Person" ) {
console.log( name );
}
print( "Alice" ); // Output: Alice
print(); // Output: Person
How to return multiple variables? Enclose them in an object or array:
return { a, b, c }; // best when values have names
return [ a, b, c ]; // best when order matters
Let's say we have an object:
const mesh = {
texture: "standard",
geometry: "sphere"
};
You can unpack the variables in this object:
let { texture, geometry } = mesh;
Note that object destructuring fetch variables with matching names:
let { tex, geometry } = mesh;
"tex" would be undefined.
Use "{}" for objects destrucutring, and "[]" for list destrucutring:
const list = [ apple, orange ];
const [ apple, orange ] = list;
List destructuring fetch variables by element order, so it doesn't matter if the name match or not:
const [ banana, melon ] = list;
Now "banana" references to "apple", and "melon" references to "orange".
In JavaScript, you need to use import to access functions and variables that are not defined in the current file:
import * as THREE from 'three'; // import everything in three library
This not only applies to external files (like libraries) but also your own file. If you have "a.js" and "b.js", you need to export from one and import into the other.
Note that functions and variables don't automatically get exported for other files to access, you need to explicitly use export to export them!
export function getName() { ... }
Here comes the confusing part: when should I use "{}" when importing?
Use {} when importing named exports:
import { something } from 'a.js';
Don't use {} when importing default exports:
Default export means a file can export only one thing without naming:
// a.js
export default function print() {
console.log( 'Hello' );
}
// you cannot export anything else in a.js!
// b.js
import print from 'a.js'; // no curly braces!
Vectors are everywhere when you're dealing with 3D graphics, but the usage of THREE.Vector is sometimes confusing.
Instantiate new vectors
const vec = new THREE.Vector3( 0, 0, 0 ); ✅
Copy value from a vector to an existing vector
Let's say we have two variables:
const vec1 = new THREE.Vector3( 0, 0, 0 );
const vec2 = new THREE.Vector3( 1, 2, 3 );
vec1.copy( vec2 ); ✅
vec1 = vec2; // "vec1" now references "vec2" ❌
Any modification made to "vec2" would also reflect on "vec1"
Clone a vector to a new variable
Let's say we have one variable:
const vec1 = new THREE.Vector3( 0, 0, 0 );
There are two ways to clone "vec1":
Option 1: "clone"
const vec2 = vec1.clone();
Option 2: "copy"
const vec2 = new THREE.Vector3(); // create a placeholder
vec2.copy( vec1 );
The difference between "clone" and "copy" is that "clone" creates and returns a new object with the same values, whereas "copy" updates the value of an existing vector
".userData" is a field defined in THREE.Object3D, the parent class of Mesh, Group, Camera, Light, etc.
This is a like tag for your objects. One of the use cases is to identify specific type of objects:
const mesh = new THREE.Mesh( geometry, material );
mesh.userData.type = "concave";
Since there is no way to tell if a mesh is concave or not (without using some custom algorithm), you can manually label concave shapes with .userData, and then process them in a batch:
scene.traverse( ( object ) => {
if ( object.isMesh && object.userData.type === "concave" ) {
// do something here
}
} );