The two languages look alike, so the differences are easy to miss. Braces, for, while, function, closures, class, try/catch, ?., ??, string interpolation and async/await have the same meaning. The differences are inside common expressions: there is no undefined, integers and floats are separate types, and reading a key that is not there is an error.
There is no undefined. Reading a slot that is not there throws, and so does reading a member of null. o?.x gives null, and ?? fills it in.
A missing slot named like a type method is not null. When t has no filter slot, t?.filter finds Table.filter. Test with "filter" in t, or write t.$filter when you want the type method.
7 / 2 is 3. Two integers divide as integers. Make one side a float.
1 / 0 throws instead of giving Infinity, and 0.0 / 0.0 throws instead of giving NaN.
"", [] and {} are true.0 and 0.0 are false, as in JavaScript, but an empty string or container is not. Test s.len() == 0.
for gives every closure the same variable, the way var did. foreach gives each pass its own. The sample below shows both.
== on two tables compares identity, like === on two objects. There is no deep comparison in the language.
+ joins when one side is a string and throws for other mixed pairs, so 1 + true throws. Use $"...". The analyzer flags + on a string as w264.
A container in a class body is one object for every instance. A JavaScript class field is built per instance; this one is not. Declare the slot as null and fill it in the constructor.
clone is an operator, not a function.clone(a).append(9) parses as clone (a.append(9)), which appends to a. Write (clone a).append(9).
examples/pages/coming-from/javascript.nut
let squad = { name = "alpha" }
// a slot that is not there is an error, not undefinedtry {
println(squad.hp)
} catch (e) {
println(e)
}
println(squad?.hp ?? 100)
// two integers divide as integers, and a division by zero throws
println(7 / 2)
local zero = 0// local: a let would fold to 0 and the analyzer would flag the divisiontry {
println(1 / zero)
} catch (e) {
println(e)
}
// for gives every closure the same variable, foreach gives each one its ownlet fromFor = []
for (local i = 0; i < 3; i++)
fromFor.append(@() i)
let fromForeach = []
foreach (v in [0, 1, 2])
fromForeach.append(@() v)
println($"for: {fromFor[0]()}{fromFor[1]()}{fromFor[2]()}")
println($"foreach: {fromForeach[0]()}{fromForeach[1]()}{fromForeach[2]()}")
Output:
the index 'hp' (type='string') does not exist
100
3
integer division by zero
for: 333
foreach: 012