簡體   English   中英

如何在許多Javascript類中引用對象而不將其傳遞給每個函數?

[英]How to reference an object in many Javascript classes without passing it into every function?

在瀏覽器中,只有創建一個gl對象后,它才會出現:

const gl = canvas.getContext('webgl2')

這意味着在class東西中引用任何gl屬性(例如gl.createBuffergl.ARRAY_BUFFER )都具有挑戰性。

在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對象,但這似乎是一個非常糟糕的主意。

我希望有一個好的,簡潔的設計范例來解決這些問題的想法。

您唯一需要做的就是確保在將值賦給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
});

我認為最常見的方法是將gl實例傳遞給構造函數(即):

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

但是,如果我每次必須進行數百次不同的調用並傳遞一個gl對象,這似乎會很煩人。

那是有充分理由的常見方式。 搜索作用域鏈直到到達全局作用域中的“ gl”對象要慢得多,特別是如果您在每幀不同功能中調用它一百次。

最好將“ gl”對象傳遞給類並創建一個實例屬性引用-這樣,您也可以在prototype-Functions中訪問“ this.gl”-無需在外部進行任何對性能至關重要的作用域鏈查找班級。

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,則良好的性能對於獲得高幀率至關重要。

當然,您可以執行其他任何操作,例如擴展類,創建單例或訪問全局屬性。 但是,如果您想要“良好,干凈的[高性能]設計”,請始終傳遞對象引用並創建本地屬性以進行快速訪問。 不要保存在錯誤的地方。

要訪問所有實例中的該屬性,您可以做的一件事就是將該變量分配給該類的原型。

您也可以使用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()) 

您可以創建一個單例,並且每次導入該單例時,它將導入相同的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
  }
}

您可以在本書中閱讀有關單調的更多信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM