Differences from standard JavaScript
HashJS is Docly's own JavaScript engine, written in .NET — not V8 and not Node.js. Most everyday JavaScript works as expected. This page lists what is missing and what behaves differently, in both .hash templates and #/API files unless noted.
Not available
Missing | Use instead |
|---|---|
Map, WeakMap | An object literal, or Set for a list of unique values. |
Symbol, Proxy | — |
Object.freeze, Object.fromEntries, Object.create, Object.groupBy | Build the object in a loop. For grouping, the Docly method array.groupBy(). |
Array: fill, findLast, findLastIndex, reduceRight, toSorted, toReversed, Array.of | slice() followed by sort() or reverse(); a for loop. |
String: search, matchAll, codePointAt | match() with the g flag, indexOf(), charCodeAt(). |
Number: toPrecision, toExponential, Number.isFinite, isFinite | toFixed(), Number.isNaN(). |
Date: toString, toLocaleString, getTimezoneOffset, and the setters (setDate, setHours, …) | format(date, pattern), toISOString(), and addDays(), addMonths() etc. to change a date. |
setTimeout, setInterval, require(), npm packages | — |
Rest parameters (function f(...args)) | The arguments object, or pass an array. Spread when calling, f(...values), does work. |
Computed property names ({ [key]: value }) and method shorthand ({ f() }) | obj[key] = value, and f: function () . |
Default import (import x from "…") | import from "…" or import * as m from "…". |
Behaves differently
Area | In HashJS |
|---|---|
Inline #…# expressions | Cannot contain a semicolon. Use a #{ … }# block for anything with ;. |
write() and #…# | null and undefined print as an empty string, and an array prints as JSON (["a","b"], not a,b). |
Reading a property of null or undefined | Throws a TypeError in .js files (as in standard JavaScript), but gives an empty value in .hash templates. |
new Error("x") | Throws immediately, even without throw in front. Call Error("x") without new to create an error object without throwing. |
JSON.stringify | A function inside the value (also a toJSON method on your own object) throws an error instead of being left out. With a replacer, for example JSON.stringify(obj, (key, value) => value), functions are left out as in standard JavaScript, but toJSON is still not called. The replacer and indent arguments otherwise work as in standard JavaScript. |
Function expressions | A named function expression (var g = function h() { … }) cannot refer to itself as h inside its body; use g. Array destructuring in the parameters of a function expression or arrow function (([a, b]) => …) is not supported; destructure in the body instead. |
switch | Each case must be a single literal value; values are compared without type conversion; default matches as soon as it is reached, so place it last. |
array.indexOf / lastIndexOf | Items are compared by their JSON representation, so an object with the same content matches. |
array.includes | Compares with .NET equality: no type conversion, objects match only the same instance. |
array.reduce | An empty array without initial value returns null instead of throwing. |
array.length = n | Does not shorten the array. |
text.match("text") | A text argument is searched for literally, not as a regular expression. |
text.replace / replaceAll with a text pattern | The replacement is inserted as is: $& and $1 are not interpreted. |
text.replaceAll(regex) | A regular expression without the g flag replaces only the first match (standard JavaScript throws). |
Object.keys / Object.entries on null | Return null instead of throwing. |
Math.min / Math.max | Also accept an array. Text that is not a number is ignored. |
Math.abs, floor, ceil, round | Text that is not a number counts as 0, and numeric text may use a comma as decimal separator. |
-2 ** 2 | Gives 4 (standard JavaScript rejects it as a syntax error). |
Number(undefined) | Gives 0 (standard JavaScript gives NaN). |
(n).toFixed(digits) | digits outside the valid range is clamped instead of throwing a RangeError. |
[] + | Gives 0. |
Object.prototype.toString.call(x) | Returns the value as text, not "[object Type]". |
Docly additions
These are not part of standard JavaScript:
Addition | Description |
|---|---|
The docly object | Docly's function library: data, files, HTTP, mail and more. All global helper functions are also available as docly.<name>. |
#…# template syntax | Expressions, code blocks and control blocks in .hash pages. See HASH files. |
array.groupBy(key) | Groups items by a property name or a function. |
Math.min(array), Math.max(array) | Accept an array as well as separate numbers. |
text.trim(chars) | Removes the given characters from both ends. |
format(value, pattern), setCulture(culture) | Formats numbers and dates; the only place a culture is used. Everything else converts numbers with a dot as decimal separator. |
Legacy template helpers | add(), cint(), where() and other global helpers from Docly's older template language. See Legacy template helpers. |