Non-native JS types (aka Scala.js-defined JS types)

A non-native JS type, aka Scala.js-defined JS type, is a JavaScript type implemented in Scala.js code.
This is in contrast to native JS types, described in the facade types reference, which represent APIs implemented in JavaScript code.

About @ScalaJSDefined

In Scala.js 0.6.x, the @ScalaJSDefined is necessary to declare a non-native JS type, also called a Scala.js-defined JS type.
Starting from Scala.js 1.x however, the annotation is not necessary anymore.
Since Scala.js 0.6.17, you can opt-in for the new semantics of 1.x where @ScalaJSDefined is not necessary, by giving the option -P:scalajs:sjsDefinedByDefault to scalac.
In an sbt build, this is done with

scalacOptions+="-P:scalajs:sjsDefinedByDefault"

The present documentation assumes that you are using this option (or Scala.js 1.x).
Code snippets mention the necessary @ScalaJSDefined in comments as a reference for older versions.

Defining a non-native JS type

Any class, trait or object that inherits from js.Any is a JS type.
Often, it will extend js.Object which itself extends js.Any:

Such classes are called non-native JS classes, and are also known as Scala.js-defined JS classes (especially in 0.6.x).
All their members are automatically visible from JavaScript code.
The class itself (its constructor function) is not visible by default, but can be exported with @JSExportTopLevel.
Moreover, they can extend JavaScript classes (native or not), and, if exported, be extended by JavaScript classes.

Being JavaScript types, the Scala semantics do not apply to these classes.
Instead, JavaScript semantics apply.
For example, overloading is dispatched at run-time, instead of compile-time.

The JavaScript names are the same as the field and method names in Scala by default.
You can override this with @JSName("customName").

private, private[this] and private[EnclosingScope] methods, getters and setters are not visible at all from JavaScript.
Private fields, however, will exist on the object, with unpredictable names.
Trying to access them is undefined behavior.

All other members, including protected ones, are visible to JavaScript.

super calls

super calls have the semantics of super references in ECMAScript 6.
For example:

classFooextendsglobal.Object{toString(){returnsuper.toString()+" in Foo";}}

which, in ES 5.1, gives something like

Foo.prototype.toString=function(){returnglobal.Object.prototype.toString.call(this)+" in Foo";};

For fields, getters and setters, the ES 6 spec is a bit complicated, but it essentially “does the right thing”.
In particular, calling a super getter or setter works as expected.

Non-native JS object

A non-native JS object is a singleton instance of a non-native JS class.
There is nothing special about this, it’s just like Scala objects.

Non-native JS objects are not automatically visible to JavaScript.
They can be exported with @JSExportTopLevel, just like Scala object: they will appear as a 0-argument function returning the instance of the object.

Non-native JS traits

Traits and interfaces do not have any existence in JavaScript.
At best, they are documented contracts that certain classes must satisfy.
So what does it mean to have native and non-native JS traits?

Native JS traits can only be extended by native JS classes, objects and traits.
In other words, a non-native JS class/trait/object cannot extend a native JS trait.
They can only extend non-native JS traits.

Unless overridden in a class or objects, concrete vals, vars and defs declared
in a JavaScript trait (necessarily with = js.undefined) are not exposed to JavaScript at all.
For example, implementing (the legal parts of) Bar in a subclass:

Note that z is not defined at all, not even as this.z = undefined.
The distinction is rarely relevant, because babar.z will return undefined in JavaScript
and in Scala.js if babar does not have a field z.

Static members

When defining a non-native JS class (not a trait nor an object), it is also possible to define static members.
Static members must be defined in the companion object of the class, and annotated with @JSExportStatic.
For example:

Note that for functions, we use js.defined { ... } to drive Scala’s type inference.
Otherwise, it needs to apply two implicit conversions, which is not allowed.

The explicit types are quite annoying, but they are only necessary in Scala 2.10 and 2.11.
If you use Scala 2.12, you can omit all the type annotations (but keep js.defined), thanks to improved type inference for vals and SAM conversions:

Caveat with reflective calls

It is possible to define an object literal with the anonymous class syntax without the support of a super class or trait defining the API, like this:

valpos=newjs.Object{valx=5valy=10}

However, it is thereafter impossible to access its members easily.
The following does not work:

println(pos.x)

This is because pos is a structural type in this case, and accessing x is known as a reflective call in Scala.
Reflective calls are not supported on values with JavaScript semantics, and will fail at runtime.
Fortunately, the compiler will warn you against reflective calls, unless you use the relevant language import.

Our advice: do not use the reflective calls language import.

Run-time overloading

Even though typechecking will resolve to the first overload at compile-time to decide the result type of the function, the actual call will re-resolve at run-time, using the dynamic type of the parameter. Basically something like this is generated:

With compile-time overload resolution, the above would be fine, as the call to bar(x: Any) resolves to the second overload, due to the static type of Any.
With run-time overload resolution, however, the type tests are executed again, and the actual run-time type of the argument is still String, which causes an infinite recursion.

Goodies

js.constructorOf[C]

To obtain the JavaScript constructor function of a JS class (native or not) without instantiating it nor exporting it, you can use js.constructorOf[C], whose signature is:

packageobjectjs{defconstructorOf[C<:js.Any]:js.Dynamic=<stub>}

C must be a class type (i.e., such that you can give it to classOf[C]) and refer to a JS class (not a trait nor an object).
The method returns the JavaScript constructor function (aka the class value) for C.

This can be useful to give to JavaScript libraries expecting constructor functions rather than instances of the classes.

js.ConstructorTag[C]

js.ConstructorTag[C] is to js.constructorOf[C] as ClassTag[C] is to classOf[C], i.e., you can use an implicit parameter of type js.ConstructorTag[C] to implicitly get a js.constructorOf[C].
For example: