2016-05-07 69 views
0

Firefox中的JavaScript代理對象似乎不適用於Web音頻對象。JavaScript代理對象不起作用

例如:

audio = new AudioContext(); 
s = audio.createOscillator(); 
s0 = new Proxy (s, {}); 
s0.connect(audio.destination); 
s0.start(); 

上述代碼應轉發關於S0所有操作爲s。但是,我收到以下錯誤:

"TypeError: 'start' called on an object that does not implement interface OscillatorNode."

我已經在此搜索了任何信息,但是沒有找到任何相關的信息。這是一個已知的錯誤/限制嗎?這些對象是否因某些明確的原因而不可代理?

感謝您對此的任何信息。

- 豐富

+1

's0'是一個標準的異國情調的對象。 'OscillatorNode's不是標準對象。當你調用'connect'時,你傳遞's0'作爲'this'的值。所以它失敗了。你爲什麼使用代理,你想達到什麼目的? – Oriol

回答

1

的問題是,當你調用一個方法上的代理,該方法將收到代理的this價值,而不是底層的對象。

function Constructor() {} 
Constructor.prototype.method = function() { 
    return this; 
}; 
var obj = new Constructor(), 
    proxy = new Proxy(obj, {}); 
obj.method(); // obj 
proxy.method(); // proxy 

在這種情況下,您的AudioContext實例是一個非標準的對象,這樣的實施可以存儲在其上實現定義的內部數據,這些數據可以用來知道它是否是一個AudioContext與否。由於代理對象僅重定向重要的內部方法,因此可以檢測到它不是AudioContext實例。

如果你確實需要使用代理的包裝,你可以嘗試添加一個get陷阱:

var audio = new AudioContext(), 
    s = audio.createOscillator(); 
s0 = new Proxy (s, { 
    get: function(target, property, receiver) { 
    var val = target[property]; 
    if(typeof val !== 'function') return val; 
    return function(...args) { 
     var thisVal = this === receiver ? target : this; /* Unwrap the proxy */ 
     return Reflect.apply(val, thisVal, args); 
    } 
    } 
}); 
s0.connect(audio.destination); 
s0.start(); 
+0

我想要做的是安排一些東西,當我在panner對象上(或者在監聽器上 - 對panner的一種特殊情況)設置一個3d panner位置時,該位置被保存在某處以便我可以查詢它後來。目前,您可以設置audioContext.listener或3d panner的位置,但不能查詢它。 我認爲一個代理對象將是重寫setPosition方法的好方法,但也許我想簡單地繼承panner或listener節點並覆蓋setPosition,並分別添加我自己的getPosition方法。 如何做到這一點? - 豐富 –

+0

我不知道這些音頻API,但似乎你在談論'PannerNode.prototype.setPosition'。由於它是繼承的,你可以嘗試'var _setPosition = panner.setPosition; panner.setPosition = function(){/ * ... */return _setPosition.apply(this,arguments); }' – Oriol