2017-01-29 2 views
2

Der folgende Code ist ein einfacher Proxy, der die „bekommt“, das gefangen wurden abmeldet:Mit beiden `get` und` apply` Proxy Fallen auf Normal JS Objekt

var p = new Proxy({}, { 
    get: function(target, property, receiver) { 
     console.log("getting: ", property); 
     return target[property]; 
    } 
}); 

Wenn ich dies in einen String coerce mit "hello " + p, erhalte ich die folgende Ausgabe in der Konsole:

getting: Symbol(Symbol.toPrimitive) 
getting: valueOf 
getting: toString 
getting: Symbol(Symbol.toStringTag) 
"hello [object Object]" 

Alles ist so weit in Ordnung, aber lassen sie sich etwas tun, ein wenig hinterhältig und Proxy eine Funktion, aber es tatsächlich noch als Proxy für unsere Ebene verwenden Objekt, das wir in den letzten e verwendet haben Beispiel. Der Grund, warum ich das möchte, ist, weil ich in der Lage sein möchte, get s und apply s auf diesem obj zu erfassen.

Hinweis der return target.obj Teil - wir verwenden diese Proxy wirklich obj noch - es ist nur, dass wir es überfn tun:

var fn = function(){}; 
fn.obj = {}; 
var p = new Proxy(fn, { 
    get: function(target, property, receiver) { 
     console.log("getting: ", property); 
     return target.obj[property]; 
    } 
}); 

Nun würde ich gedacht hätte dies produzieren genau die gleiche Leistung wie das letzte Beispiel für "hello " + p, aber ich war falsch:

getting: Symbol(Symbol.toPrimitive) 
getting: valueOf 
getting: toString 
getting: Symbol(Symbol.toStringTag) 
"hello [object Function]" 

Beachten sie, dass es in einem Function String geführt hat ta g statt einer Object eins. Was ist denn hier los? Es ist, als würde toString unter fn anstelle von obj aufgerufen. (Edit: Aber wir können fn.toString = function(){ return "fn"; } hinzufügen und nicht den Ausgang ändern, so ist es vielleicht nicht fn dass hier Zeichenfolge wird?)

Wenn Sie eine debugger Anweisung pop es in, Sie werden sehen, es ist eigentlich Rückkehr fn.obj.toString wie Sie erwarten, aber aus irgendeinem Grund ist die endgültige Ausgabe eine Funktion und kein Objekt (obwohl ich nicht ganz sicher bin welche Funktion). Danke für Ihre Hilfe!

P.S. Ich habe nicht den vollständigen Kontext meines Anwendungsfalls erklärt (kurze Version: es ist für eine DSL, also ist das Biegen "guter Praxis" in Ordnung), und schlägt so alternative Muster vor, um sowohl get als auch apply Fallen auf einem Objekt zu erreichen (in der Tat) möglicherweise nicht relevant für meinen speziellen Fall. Ich möchte wirklich nur verstehen, warum der obige Ansatz nicht so funktioniert, wie ich es erwarte, aber ich möchte auch sicherstellen, dass die Frage breit genug ist, um zukünftigen Lesern in einer ähnlichen Situation zu helfen.

Antwort

0

Ich denke, ich habe den Fehler gefunden. Wenn wir eine Funktion zurückgeben, sieht es so aus, als müssten wir bind an target.obj senden, sonst wird es irgendwo an eine Funktion gebunden. Ich bin nicht ganz bei Null auf this Sachen, aber ich denke, es macht Sinn. Also hier ist der aktualisierte, funktionierende Code:

var fn = function(){}; 
fn.obj = {}; 
fn.toString = function(){ return "fn"; } 
var p = new Proxy(fn, { 
    get: function(target, property, receiver) { 
     console.log("getting: ", property); 
     let result = target.obj[property]; 
     if(typeof result === 'function') { 
      result = result.bind(target.obj); 
     } 
     return result; 
    } 
}); 
+1

Sehr interessantes Problem! Noch mehr Forschung zu tun, bevor ich genau verstehe, was los ist, obwohl [die Spezifikation] (http://www.ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) zeigt, warum Ihre Bindung Dieser Wert ist wichtig. – Gerrit0

Verwandte Themen