-
Notifications
You must be signed in to change notification settings - Fork 1
Using JSObj and JSVar
There are 4 main ways to use Javascript's objects from D.
Generally not recommended, JSVar usually does its job better. In cases where the JS object only has fields of one type and no functions, an associative array can be used. This is an eager by-value conversion and modifications on the D side don't produce effects on the original object.
void withAA (int [string] foo) {
import std.stdio;
writeln (foo ["bar"]);
// This only changes D's AA, not the original JS object
foo ["baz"] = 4;
assert (foo ["baz"] == 4);
}These are eager by-value conversion. Functions of the object cannot be called. Recommended when all declared fields are used, the original object doesn't need to be modified. Has the advantage of early type validation and multiple access to a field doesn't have the JS overhead.
struct Person {
string name;
uint age;
}
void withStruct (Person p) {
import std.stdio;
writeln (p.name, ": ", p.age, " Y.");
}This is a struct provided by Node dlang that wraps a Javascript value and environment. Works lazily by-reference. Similar to Javascript usage. Doesn't need a struct declaration describing it but also doesn't perform as much compile time type validations as a JSObj. Fields modified are also modified on the original object. Allows calling member functions.
// Extracts and returns int field 'foo', from someObj.
// Sets the value of someObj.someVal to someObj.otherVal (5)
// Failure to extract a field or cast the result to int results in an assertion error.
int withJSVar (JSVar someObj) {
someObj ["someVal"] = someObj.otherVal (5);
return cast (int) someObj ["foo"];
}Notice that when using fields, index syntax is used and when calling functions, the dot syntax is used.
In D someObj.someVal = someObj.otherVal (5); is automatically converted to someObj.someVal (someObj.otherVal (5)), so JSVar cannot use the same syntax as JS in those cases, ["fieldName"] must be used for accessing and setting fields.
JSObj allows the dot syntax as opDispatch isn't implemented there.
When the object corresponds to a JS type, using theObj.constructor () allows instancing it.
Similarly to JSVar, works lazily by-reference. Requires using the JSObj template with an argument consisting of a struct defining the structure of the corresponding Javascript object. Has three main advantages over JSVar: it prevents errors from using a field/function with wrong name or parameter types (assuming correct declaration of those in the struct) and also allows the similar to JS dot notation for accessing and setting fields:
struct Spooky {
int foo;
string otherVal (int num);
string someVal;
}
int withJSObj (JSObj!Spooky someObj) {
// Failure to extract/set/convert the values to/from the correct types
// results in an assertion error.
// Compare to JSVar syntax.
// This modification is done on the original JS object.
someObj.someVal = someObj.otherVal (5);
// Manual cast is not needed
return someObj.foo;
}