简体   繁体   English

scalajs范围内的对象与js.global范围内的* same *对象之间有什么区别?

[英]What's the difference between object in scalajs scope and *same* object in js.global scope?

I'm trying to write a simple example to render cube with THREEJS lib. 我正在尝试编写一个简单的示例以使用THREEJS lib渲染多维数据集。

package three

import org.scalajs.dom

import scala.scalajs.js
import scala.scalajs.js.Dynamic._
import scala.scalajs.js.annotation.JSName

object THREE extends js.Object
{
  @JSName ("THREE.Scene")
  class Scene extends js.Object
  {
       def add(obj: js.Object) = ???
  }

  @JSName ("THREE.Vector3")
  class Vector3(var x:js.Number, var y:js.Number, var z:js.Number) extends js.Object

  @JSName ("THREE.PerspectiveCamera")
  class PerspectiveCamera(a:js.Number,b:js.Number,c:js.Number,d:js.Number) extends js.Object
  {
    var position:Vector3 = _
  }

  @JSName ("THREE.WebGLRenderer")
  class WebGLRenderer(params:js.Dynamic) extends js.Object
  {
    def render(scene:js.Object, camera:js.Object) = ???
  }

  @JSName ("THREE.WebGLRenderer")
  class SimpleWebGLRenderer() extends js.Object
  {
    def render(scene:js.Object, camera:js.Object) = ???
    var domElement : js.Dynamic = _
  }

  @JSName ("THREE.BoxGeometry")
  class BoxGeometry(a:js.Number,b:js.Number,c:js.Number) extends js.Object

  @JSName ("THREE.MeshBasicMaterial")
  class MeshBasicMaterial(params:js.Dynamic) extends js.Object

  @JSName ("THREE.MeshBasicMaterial")
  class SimpleMeshBasicMaterial() extends js.Object

  @JSName ("THREE.Mesh")
  class Mesh(geometry:js.Object, material:js.Object) extends js.Object

}


object ThreeExample
{
  def render() =
  {
    val scene = new THREE.Scene()
    val camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
    val renderer = new THREE.WebGLRenderer(js.Dynamic.literal(
      canvas = global.document.getElementById("ThreeCanvas")
    ));
    val geometry = new THREE.BoxGeometry(1,1,1);
    val material = new THREE.SimpleMeshBasicMaterial()
    camera.position.z = 2;
    val cube = new THREE.Mesh(geometry, material);

Now the fun part. 现在有趣的部分。 If I try to write 如果我尝试写

scene.add(cube);
renderer.render(scene, camera);

I get 我懂了

ScalaJS.c.jl_ClassCastException {s$1: "[object Object] is not an instance of scala.runtime.Nothing$", e$1: null, stackTrace$1: null, stackdata: TypeError, constructor: function…} ScalaJS.c.jl_ClassCastException {s $ 1:“ [object Object]不是scala.runtime.Nothing $的实例”,e $ 1:null,stackTrace $ 1:null,stackdata:TypeError,构造函数:function…}

error. 错误。 While if I try 如果我尝试

global._scene = scene
global._cube = cube
global._camera = camera
global._renderer = renderer

global._scene.add(global._cube)
global._renderer.render(global._scene, global._camera);

everything renders correctly w/o errors. 一切都正确呈现,没有错误。 I mean, what's the catch? 我的意思是,有什么收获? Is there a difference between global._scene and scene or global._scene.add and scene.add ? global._scene和scene或global._scene.add和scene.add之间有区别吗?

To elaborate on my comment: there is basically no difference. 详细说明一下:基本上没有区别。 The statically typed interface is only a typed facade to the same mechanisms that are used with the dynamically typed interface. 静态类型化接口只是与动态类型化接口所使用的相同机制的类型化外观。 However, because it is static, it adds checks to the values returned by the methods you call. 但是,由于它是静态的,因此它将对您调用的方法返回的值添加检查。

In your case, when calling renderer.render() , the compiler adds a check that the value returned by this JavaScript method actually conforms to the static result type of WebGLRenderer.render() . 在您的情况下,在调用renderer.render() ,编译器会添加一个检查,以确保此JavaScript方法返回的值实际上符合WebGLRenderer.render()的静态结果类型。 But what is this result type? 但是这种结果类型是什么? It's Nothing ! Nothing Why is that? 这是为什么? Because the body of this method is ??? 因为此方法的主体是??? , which is of type Nothing , so scalac infers the method's result type as Nothing . ,其类型为Nothing ,因此scalac推断该方法的结果类型为Nothing The check then fails, because the value returned by render from JavaScript is not of type Nothing (obviously, since no value has that type), which causes the ClassCastException . 然后检查失败,因为JavaScript的render返回的值不是Nothing类型(显然,因为没有值具有该类型),这导致ClassCastException

What you wanted is obviously not Nothing , but rather Unit . 您想要的显然不是Nothing ,而是Unit So all you have to do is to make explicit this result type with : Unit like this: 因此,您要做的就是使用: Unit明确显示此结果类型:

def render(scene:js.Object, camera:js.Object): Unit = ???

In general, you should always specify explicitly the result type of methods in facade types, because otherwise they're inferred as Nothing , which is not what you want. 通常,您应该始终在Facade类型中明确指定方法的结果类型,因为否则将它们推断为Nothing ,这不是您想要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM