2017-02-01 3 views
2

Scala.js фасад для нативного типов JS может выглядеть следующим образом (от Three.js facade):Scala.js родной Конструкторы Javascript

@js.native 
@JSName("THREE.Vector3") 
class Vector3 extends Vector { 
    def this(x: Double = js.native, y: Double = js.native, z: Double = js.native) = this() 
    var x: Double = js.native 
    var y: Double = js.native 
    var z: Double = js.native 

/* ... */ 
} 

Соответствующий Javascript definition функции строящейся Vector3 является:

function Vector3(x, y, z) { 

    this.x = x || 0; 
    this.y = y || 0; 
    this.z = z || 0; 

} 

Я прочитал документы о creating Scala.js facades, однако конструкторы здесь кратко упоминаются. Код с фасада отлично работает в реальном коде, однако я не уверен, правильное определение и почему и как оно работает.

  • фасад не позволяет конструктору аргументов.
  • конструктор с аргументами просто вызывает конструктор без аргументов. Тем не менее объект, кажется, сконструирован отлично, с элементом, установленным на переданные значения.
  • конструктор использует значение js.native как значение по умолчанию для всех аргументов. Должны ли все фасады определять конструкторы таким образом?

Esp. второй момент меня смущает. Как это может работать? Во всех трех случаях я хотел бы знать, какой код JS генерируется для конструктора и почему.

Можно также представить себе, как писать фасад. Правильно ли это?

class Vector3(var x: Double = js.native, var y: Double = js.native, var z: Double = js.native) extends Vector { 

/* ... */ 
} 

ответ

2

Данное определение является правильным. Правила фасадов для строителей JavaScript довольно просто заявил: при встрече вызова, такие как

new C(arg1, ..., argN) 

и C класс JavaScript, это приводит к

new Cconstr(arg1, ..., argN) 

где Cconstr является результатом оценки js.constructorOf[C] , Для родного класса JavaScript js.constructorOf[C] ищет в глобальной области имя C (или применяется @JSName или @JSImport правил). В частности, в вашем примере, вызов, такие как

new Vector3(3, 4, 5) 

переводит

new <global>.THREE.Vector3(3, 4, 5) 

Примечание, в частности, что тело определений конструктора совершенно не имеет значения, так как сайт вызова напрямую вызывает JavaScript-код в библиотеке Three.js. Следовательно, тот факт, что конструктор 3-arg вызывает конструктор 0-arg и игнорирует его аргументы, просто игнорируется семантическими правилами. Вызов необходим для соблюдения правил проверки типов Scala, но семантически не имеет значения.

Аналогично, фактическое значение значений по умолчанию семантически не имеет значения. Их присутствие делает параметры необязательными, но их значение в противном случае игнорируется компилятором.Вызов таких как

new Vector3(3) 

переводит в JavaScript для

new <global>.THREE.Vector3(3) 

, в котором y и z параметры вообще не дали, оставив JavaScript, чтобы решить, что делать с ними.

Наконец, ваше альтернативное определение:

class Vector3(var x: Double = js.native, var y: Double = js.native, var z: Double = js.native) 

только равноценны. Он не имеет явного конструктора 0-arg, но его также можно «получить доступ», указав аргумент 0 конструктору, который имеет 3 необязательных параметра. Это определение, конечно, более кратким, хотя и выглядит немного более Scala-esque, поэтому я бы лично определил его таким образом. Но это уже не правильно, чем первоначальный.

Смежные вопросы