JavaScript Mapping for Dictionaries

Here is the definition of our EmployeeMap once more:

Slice
dictionary<int, Employee> EmployeeMap;

In the JavaScript mapping, dictionaries using a JavaScript built-in type as the key type are mapped to the JavaScript Map type. This is true for all Slice built-in types except long, the Slice-to-JavaScript compiler generates a type alias for Map with the same name as the Slice dictionary, the generated code is equivalent to:

EmployeeMap = Map;
class EmployeeMap extends Map<number, Employee>{}
JavaScript
const em = new EmployeeMap();

const e = new Employee();
e.number = 31;
e.firstName = "James";
e.lastName = "Gosling";

em.set(e.number, e);

In JavaScript using EmployeeMap allows to better declare our intention in the code but as far as the Ice run-time is concerned using Map will be equally fine, the same goes for TypeScript using EmployeeMap is convenient but as far as the compiler is concerned using a type that implements Map<number, Employee> will be fine


For cases where the key type does not correspond with a JavaScript built-in type, the dictionary is mapped to Ice.HashMap. This is true for Slice dictionaries where the key type is long or a Slice structure that qualifies as a legal dictionary key:

Slice
dictionary<long, Employee> EmployeeMap;

In these cases an extra constructor is generated that initializes the Ice.HashMap with the desired comparison operator.

class EmployeeMap extends Ice.HashMap
{
    constructor(h)
    {
        super(h || keysEqual);
    }
}
class EmployeeMap extends Ice.HashMap<Ice.Long, Employee>{}
JavaScript
const em = new EmployeeMap();

const e = new Employee();
e.number = new Ice.Long(31);
e.firstName = "James";
e.lastName = "Gosling";

em.set(e.number, e);

The mapping for dictionaries in TypeScript is the same, the only difference is that the TypeScript compiler will enforce the Key and Value types when using the TypeScript definitions generated by Slice-to-JavaScript compiler.


Ice.HashMap supports the same API as the standard JavaScript Map object. It provides the following additional properties and functions:

  • HashMap.prototype.constructor(keyComparator, valueComparator)
    This version of the constructor accepts optional comparator functions that the map uses to compare keys and values for equality. If you instantiate a map directly using new Ice.HashMap() without specifying comparator functions, the default comparators use the === operator to compare keys and values. As an example, the following map compares its keys and values using equals methods:

    JavaScript
    function compareEquals(a, b)
    {
        return a.equals(b);
    }
    const m = new Ice.HashMap(compareEquals, compareEquals);
    



    The valueComparator function is only used when comparing two maps for equality.

    The type-specific constructor generated for a Slice dictionary supplies comparator functions appropriate for its key and value types.

  • HashMap.prototype.equals(other, valueComparator)
    Returns true if this map compares equal to the given map, false otherwise. You can optionally supply a function for valueComparator that the map uses when comparing values; this function takes precedence over the comparator supplied to the map's constructor.
  • HashMap.prototype.clone()
    Returns a shallow copy of the map.

Legal key types for Ice.HashMap include JavaScript's primitive types along with nullNaN, and any object that defines a hashCode method. The generated code for a Slice structure that qualifies as a legal dictionary key type includes a hashCode method. Suppose we define another dictionary type:

Slice
dictionary<Employee, string> EmployeeDeptMap;

The Slice compiler generates a constructor function equivalent to the following code:

JavaScript
class EmployeeDeptMap extends Ice.HashMap
{
    constructor(h)
    {
        const keyComparator = ...;
        const valueComparator = ...;
        super(h || keyComparator, valueComparator);
    }
}
TypeScript
class EmployeeDeptMap extends Ice.HashMap<Employee, string>
{
}


Since the key is a user-defined structure type, the map requires a comparator that properly compares keys. Instantiating a map using new EmployeeDeptMap automatically sets the comparators, whereas calling new Ice.HashMap in this case would require you to supply your own comparators.

Slice dictionaries that map to a HashMap must be instantiated using the generated constructor.

Notes

  • Attempting to use the map[key] = value syntax to add an element to the map will not have the desired effect; you must use the set function instead.


See Also