[英]How to reference an object in many Javascript classes without passing it into every function?
在瀏覽器中,只有創建一個gl
對象后,它才會出現:
const gl = canvas.getContext('webgl2')
這意味着在class
東西中引用任何gl
屬性(例如gl.createBuffer
或gl.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
關鍵字從父類擴展屬性。 在下面的代碼中, App
和App2
使用來自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.