如何引用许多Javascript类中的对象而不将其传递给每个函数?

时间:2017-05-01 06:53:26

标签: javascript

在浏览器中没有gl对象,直到你创建一个:

const gl = canvas.getContext('webgl2')

这意味着在gl之类的内容中引用任何gl.createBuffer属性(如gl.ARRAY_BUFFERclass)具有挑战性。

在C ++中包含这些对象,因此无需gl的特定实例即可访问。

如何创建一个具有成员变量的类,该成员变量的值设置为gl对象的某个属性?

例如:

class App {
  constructor () {
     this.VBO = gl.createBuffer() // gl is not defined here
  }
}

我认为最常见的方法是将gl实例传入构造函数(即。):

class App {
  constructor (gl) {
     this.VBO = gl.createBuffer() // gl is passed in
  }
}

但是,如果我每次必须进行数百次不同的调用并传入gl对象,这似乎会让人讨厌。

另外我想我可以定义某种全局gl对象: gl = canvas.getContext('webgl2')然后假设在需要访问的地方有一些全局gl对象,但这似乎是一个非常糟糕的主意。

我很欣赏任何关于良好,干净的设计范例的想法,以解决这些问题。

4 个答案:

答案 0 :(得分:1)

您唯一需要做的就是确保在将值分配给gl之前不执行任何类实例化代码,然后在相同的上下文中定义gl课程。例如:

document.addEventListener('DOMContentLoaded', function() {
    class App {
        constructor () {
             this.VBO = gl.createBuffer() // gl is defined when getting here
        }
    }

    const canvas = document.getElementById('mycanvas'),
          gl = canvas.getContext('webgl2'),
          app = new App();
    // ... etc
});

如果您的类是在函数上下文之外定义的并且无法更改,那么在全局对象上定义gl

class App {
    constructor () {
         this.VBO = window.gl.createBuffer() // gl is defined when getting here
    }
}

document.addEventListener('DOMContentLoaded', function() {
    var canvas = document.getElementById('mycanvas');
    window.gl = canvas.getContext('webgl2');
    var app = new App();
    // ...etc
});

答案 1 :(得分:1)

  

我认为最常见的方法是将gl实例传入   构造函数(即):

class App {
  constructor (gl) {
     this.VBO = gl.createBuffer() // gl is passed in
  }
}
  

但是,如果我必须制作数百个,这似乎会让人讨厌   不同的调用并每次传入一个gl对象。

这是有充分理由的常见方式。搜索范围链直到您到达" gl"全局范围内的对象要慢得多,特别是如果你在每帧不同的函数中调用它一百次。

最好将" gl" -object传递给一个类并创建一个instance-property-reference - 这样你就可以访问" this.gl"在prototype-Functions中 - 在类之外没有任何性能关键的范围链查找。

class App {
  constructor(gl) { //pass gl
     this.gl = gl; // always create a instance-property for fast access
     this.VBO = this.gl.createBuffer(); // access methods through "this.gl"
     this.foo = new FooGL(gl); // pass "gl" to other classes
  }

  abc() {
     this.gl.doSomeThingABC(); // access methods through "this.gl"
     this.foo.doSomething(); // FooGL has his own "gl" instance-property
                             // to access methods through its own "this.gl"
  }
}
// or
App.prototype.xyz = function()
{
    return this.gl.doSomeThingXYZ(); // access methods through "this.gl"
}

const gl = document.createElement('canvas').getContext('webgl2');
const app = new App(gl);

这是获得高性能的最佳方法,即使它需要编写更多代码。如果您使用WebGL,良好的性能是实现高帧率的最重要因素。

当然,您可以执行任何其他操作,例如扩展类,创建单例或访问全局属性。但是如果你想要"好,干净[和高性能]设计",总是传递对象引用并创建一个本地属性以便快速访问。不要把钱存在错误的地方。

答案 2 :(得分:0)

在所有实例中访问该属性可以做的一件事是将该变量分配给该类的原型。

此外,您可以使用extends关键字来扩展父类的属性。在下面的代码AppApp2中使用来自Parent protype的相同函数fun2

class Parent{
  constructor() {
    this.fun = function(){
     return 'An instance property '
    }
  } 
}

Parent.prototype.fun2 = function(){
  return 'not an instance property'
}

class App extends Parent{
 
  constructor () {
     super();
     this.VBO = App.gl.createBuffer() 
  }
}

App.gl = {
 createBuffer : function(){
   console.log('from App prototype ')
 }
}

var a = new App();
console.log(a.fun())

class App2 extends Parent{

}

var a2 = new App2();
console.log(a2.fun())
console.log(a2.fun2())

答案 3 :(得分:0)

您可以创建单身人士,每次导入该单身人士时,都会导入相同的gl

// gl.js    
const gl = canvas.getContext('webgl');

export default gl;

// class1.js
import gl from './gl.js';
class App {
  constructor () {
     this.VBO = gl.createBuffer() // gl is not defined here
  }
}

// class2.js
import gl from './gl.js'; // exactly the same gl
class B {
  constructor () {
     this.VBO = gl.createBuffer() // gl is not defined here
  }
}

您可以在此book中详细了解单身人士。