-
-
Notifications
You must be signed in to change notification settings - Fork 5
Language
DScript is syntactically close to JavaScript (ES2020+). This page covers every supported language construct.
var x = 10; // function-scoped, hoisted
let y = 20; // block-scoped, not hoisted
const PI = 3.14; // block-scoped, immutable bindinglet and const obey block scoping — they are not visible outside the {} block they are declared in.
globalThis refers to the global scope object from any context:
var x = 1;
globalThis.x; // 1
globalThis.y = 2; // same as var y = 2 at the top level| Type | Example literals |
|---|---|
| Number (integer) |
0, 42, -7, 0xFF, 0b1010, 0o17, 1_000, 0xFF_FF, 0b1010_0001, 0o7_7
|
| Number (float) |
3.14, -0.5, 1e10, 1_000.5, 1_000e2
|
| String |
"hello", 'world', `template`
|
| Boolean |
true, false (stored as 1 / 0) |
| Null | null |
| Undefined | undefined |
| Object | { key: value } |
| Array | [1, 2, 3] |
| Function |
function f() {}, x => x
|
Underscores (_) may be used as visual separators inside any numeric literal. They are ignored by the parser and do not affect the value.
var million = 1_000_000; // integer
var pi = 3.141_592_653; // float
var scientific = 1_000e2; // exponent form
var hex = 0xFF_FF; // hex
var bits = 0b1010_0001; // binary
var octal = 0o7_7; // octalInvalid positions (throw SyntaxError):
- Immediately after a prefix (
0x_,0b_,0o_) - Immediately after a decimal point (
1._5) - Immediately after an exponent marker (
1e_2) - At the end of a literal (
100_) - Two consecutive separators (
1__000)
| Category | Operators |
|---|---|
| Arithmetic |
+ - * / % ++ -- (prefix and postfix), unary + -
|
| Assignment |
= += -= *= /= %= &= |= ^= <<= >>= >>>= &&= ||= ??=
|
| Comparison |
< > <= >= == != === !==
|
| Logical |
&& || !
|
| Bitwise |
& | ^ ~ << >> >>>
|
| Nullish / optional |
?? ?.
|
| Other |
?: ternary, typeof, instanceof, in, delete, new, ... spread |
var name = "Alice";
var msg = `Hello, ${name}! You are ${20 + 5} years old.`;Any expression may appear inside ${}. Nested template literals are allowed.
// Object literal
var obj = { x: 1, y: 2 };
// Shorthand property (name === value)
var name = "bob";
var record = { name, score: 100 }; // { name: "bob", score: 100 }
// Computed key
var key = "color";
var car = { [key]: "red" }; // { color: "red" }
// Property access
obj.x; // dot notation
obj["y"]; // bracket notation
// Property deletion
delete obj.x;var arr = [10, 20, 30];
arr[0]; // 10
arr.length; // 3
arr.push(40); // append
arr.pop(); // remove last// Named declaration (hoisted)
function add(a, b) { return a + b; }
// Anonymous expression
var mul = function(a, b) { return a * b; };
// Arrow — expression body (implicit return)
var sq = x => x * x;
var sum = (a, b) => a + b;
// Arrow — block body
var clamp = (v, lo, hi) => {
if (v < lo) return lo;
if (v > hi) return hi;
return v;
};
// Default parameters
function greet(name, msg = "Hello") {
return `${msg}, ${name}!`;
}
// Rest parameters
function first(head, ...tail) { return head; }
// Spread in calls
function add3(a, b, c) { return a + b + c; }
add3(...[1, 2, 3]); // 6Every function captures its enclosing lexical scope:
function counter() {
var n = 0;
return () => ++n;
}
var inc = counter();
inc(); // 1
inc(); // 2
inc(); // 3function Animal(name) {
this.name = name;
}
Animal.speak = function() {
return `${this.name} makes a sound`;
};
function Dog(name) {
Animal.call(this, name);
}
Dog.prototype = new Animal();
var d = new Dog("Rex");
d.speak(); // "Rex makes a sound"
d instanceof Dog; // true
d instanceof Animal; // trueclass syntax is also accepted:
class Shape {
constructor(color) {
this.color = color;
}
describe() {
return `A ${this.color} shape`;
}
}
class Circle extends Shape {
constructor(color, r) {
super(color);
this.radius = r;
}
area() {
return Math.PI * this.radius * this.radius;
}
}// Array
var [a, b, c] = [1, 2, 3];
var [x, , z] = [10, 20, 30]; // skip middle
var [head, ...rest] = [1, 2, 3, 4]; // rest = [2,3,4]
// Object
var { x, y } = { x: 1, y: 2 };
var { name: alias } = { name: "alice" }; // rename
var { score = 0 } = {}; // default
var { a: { b } } = { a: { b: 99 } }; // nested// Array spread
var a = [1, 2];
var b = [...a, 3, 4]; // [1,2,3,4]
// Object spread
var base = { x: 1 };
var ext = { ...base, y: 2 }; // { x:1, y:2 }var x = null;
var y = x ?? "default"; // "default"
var obj = { a: { b: 42 } };
obj?.a?.b; // 42
obj?.z?.w; // undefined (no throw)
obj?.fn?.(1, 2); // undefined if fn absentShort-circuit compound assignments — the RHS is only evaluated when needed.
a &&= b // assign b to a only if a is truthy (a && (a = b))
a ||= b // assign b to a only if a is falsy (a || (a = b))
a ??= b // assign b to a only if a is null or undefined
// All three also work on property and index targets:
obj.x &&= computeNewValue();
arr[i] ??= defaultValue;// if / else if / else
if (x > 0) { ... } else if (x < 0) { ... } else { ... }
// while
while (cond) { ... }
// do / while
do { ... } while (cond);
// for
for (var i = 0; i < 10; i++) { ... }
// for...in — property names
for (var key in obj) { console.log(key); }
// for...of — iterable values (arrays, generators, …)
for (var val of [1, 2, 3]) { console.log(val); }
// switch — no fallthrough; default may appear anywhere
switch (x) {
case 1: ...; break;
default: ...;
case 2: ...;
}
// break / continue
while (true) {
if (done) break;
if (skip) continue;
}continue inside a switch that is nested inside a loop targets the loop, not the switch.
try {
throw new Error("something went wrong");
} catch (e) {
console.log(e.message);
} finally {
// always runs
}
// Throw any value
throw { code: 404, message: "not found" };function* range(start, end) {
for (var i = start; i < end; i++) yield i;
}
for (var n of range(0, 5)) console.log(n); // 0 1 2 3 4
var gen = range(0, 3);
gen.next(); // { value: 0, done: false }
gen.next(); // { value: 1, done: false }
gen.next(); // { value: 2, done: false }
gen.next(); // { value: undefined, done: true }Generators that contain no try/catch use a stackless state-machine path.
async function fetchUser(id) {
var data = await loadFromDb(id);
return data.name;
}
fetchUser(1).then(name => console.log(name));After engine.Run(program), call engine.DrainMicroTasks() from C# to flush the microtask queue and settle all pending promises.
var p = new Promise((resolve, reject) => {
resolve(42);
});
p.then(v => console.log("resolved:", v))
.catch(e => console.log("rejected:", e));
// Static constructors
Promise.resolve(1);
Promise.reject("err");
Promise.all([p1, p2, p3]);
Promise.allSettled([p1, p2]);
Promise.race([p1, p2]);
Promise.any([p1, p2]);/pattern/flags // literal
new RegExp("pattern", "flags") // constructor
/hello/i.test("Hello World"); // true
/(\d+)/.exec("abc123"); // ["123", "123"]
var s = "hello world";
s.match(/\w+/g); // ["hello", "world"]
s.replace(/o/g, "0"); // "hell0 w0rld"Supported flags: g (global), i (ignoreCase), m (multiline).
typeof 42; // "number"
typeof "hi"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object"
typeof {}; // "object"
typeof []; // "object"
typeof function(){}; // "function"
[] instanceof Array; // truevar obj = { a: 1, b: 2 };
"a" in obj; // true
delete obj.a;
"a" in obj; // false