2016-05-10 30 views
0

Ich habe eine ziemlich nützliche Funktion zur Identifizierung von Datentypen konstruiert; Aber während ich glücklich codierte, wurde ich grob durch ein ziemlich beunruhigendes Dilemma unterbrochen.JavaScript - Zugriff auf Eigenschaften nach (Schließung) .bind()

Wie Sie vielleicht wissen, können Sie nach dem Aufruf .bind({foo:'bar'}) auf eine Schließung nicht zugreifen foo Eigenschaft "extern"; Innerhalb des Verschlusses funktioniert this.foo jedoch.

Auch wenn Sie etwas so zuweisen, stehen Sie oft vor einem Wurf: intermediary ... blah blah is undefined, wenn Sie versuchen, auf eine Eigenschaft zuzugreifen - direkt nach der Definition. Der folgende Code behebt diese Probleme, aber ...

Das Problem nach dem Code erklärt:

"use strict"; 

if ('undefined' == typeof global) 
{ 
    Object.defineProperty 
    (
     window,'global', 
     { 
      writable:false, 
      configurable:false, 
      enumerable:false, 
      value:window 
     } 
    ); 
} 


Object.defineProperty 
(
    Function.prototype, 'wrap', 
    { 
     writable:false, 
     enumerable:false, 
     configurable:false, 

     value:function(jsob) 
     { 
      this.bind(jsob); 

      for (var i in jsob) 
      { this[i] = jsob[i]; } 

      return this; 
     } 
    } 
); 


global.typeOf = function(data) 
{ 
    if ((data === null) || (data === undefined)) 
    { return 'void'; } 

    if ((data === true) || (data === false)) 
    { return 'bool'; } 

    var tpof = (({}).toString.call(data).match(/\s([a-zA-Z]+)/)[1].toLowerCase()); 

    if ((tpof == 'array') || (tpof == 'htmlcollection') || (tpof == 'namednodemap')) 
    { return 'list'; } 

    if ((tpof == 'global') || (tpof == 'window')) 
    { return 'glob'; } 

    switch (tpof.substr(0,6)) 
    { 
     case 'number': return 'unit'; 
     case 'string': return (/[^\x20-\x7E\t\r\n]/.test(data) ? 'blob' : 'text'); 
     case 'object': return 'jsob'; 
     case 'functi': return 'func'; 

     default: return 'node'; 
    } 
} 
.wrap 
({ 
    list:'void bool unit text blob list jsob func node glob'.split(' '), 
    init:function() 
    { 
     this.list.forEach(function(item) 
     { 
      global[(item.toUpperCase())] = item; 
      global[('is'+(item[0].toUpperCase() + item.substr(1,item.length)))] = function(data) 
      { 
       return ((typeOf(data) == this.text) ? true : false); 
      } 
      .bind({text:item.toLowerCase()}); // <-- ISSUE 
     }); 

     return this; 
    } 
}).init(); 

So der kleine wrapper oben kümmert sich um solche Verrücktheit; Sehen Sie sich jedoch die Zeile <-- ISSUE an. siehe, ich kann wrap() dort nicht verwenden, muss ich bind() verwenden, sonst - innerhalb der Funktion - this ist undefined !!

Lassen Sie mich klarstellen: Wenn Sie den gesamten Code verwenden, wie es oben in <script> Tags innerhalb einer Brand-Spanking-neue HTML-Datei ist; Ändern Sie einfach das ISSUE Linie bind Wort zu: wrap; versuchen dann so etwas wie: isText("bite me!");

Sie einen Fehler sehen, dass so etwas gibt: von undefined

kann nicht lesen Eigenschaft "text" ..

so; wenn Sie eine console.log(this) innerhalb dieser Funktionsdefinition dort machen; Sie werden undefined sehen.

Wenn jemand helfen könnte, dies zu beheben, oder zumindest erklären, warum dies geschieht, würde ich den Input sehr schätzen.

+0

@Kashif :: Die 'wrap()' Methode ermöglicht den Zugriff auf Eigenschaften -extern von der Schließung. Es verkürzt auch den Code, der benötigt wird. – argon

+0

@deceze :: der ganze Code könnte Teil des Problems sein; und - der Code ist wie er ist verwendbar, einfach kopieren + einfügen & test; nichts "fehlt" überhaupt. – argon

+1

Scheint so, als ob das Problem, mit dem Sie es zu tun haben, dasselbe ist wie das, das Sie beheben wollen. Die eingepackten isX-Funktionen können nicht von dem umschlossenen Verschluss auf "dieses" zugreifen. Ich vermute, du fragst praktisch nach einer Erklärung für deine "Mistlosigkeit" – Tibrogargan

Antwort

1

Ich sehe absolut keinen Zweck für diese wrap Funktion. In der Tat gibt es keinen Grund, this oder bind für diesen Anwendungsfall überhaupt zu verwenden. Tun Sie einfach

global.typeOf = function(data) { 
    if (data == null) return 'void'; 
    switch (typeof data) 
     case "boolean": return 'bool'; 
     case "number": return 'unit'; 
     case "string": return /[^\x20-\x7E\t\r\n]/.test(data) ? 'blob' : 'text'; 
    } 
    switch (Object.prototype.toString.call(data).slice(8, -1).toLowerCase()) { 
     case "array": 
     case "htmlcollection": 
     case "namednodemap": return 'list'; 
     case "global": 
     case "window": return 'glob'; 
     case "object": return 'jsob'; 
     case "function": return 'func'; 
     default: return 'node'; 
    } 
}; 
global.typeOf.list = 'void bool unit text blob list jsob func node glob'.split(' '); 

global.typeOf.list.forEach(function(item) { 
    global[item.toUpperCase()] = item; 
    global['is'+item[0].toUpperCase()+item.slice(1)] = function(data) { 
     return typeOf(data) == item; 
    } 
}); 
+0

Der Punkt der "Bindung" (Umbruch) ist, dass die Liste der primären Typen an einer Stelle enthalten sein sollte, wo sie hingehört, weil ich auch eine andere Funktion habe: "kindOf" - die nach sekundären Datentypen sucht und eine Referenz von benötigt welche Konstanten und Funktionen entsprechend benennen und definieren. Es kann getan werden, indem man es nur nachher zuweist, aber ich suche nach einer Möglichkeit, es einmal zuzuweisen, ohne "typeOf" außerhalb seines eigenen Bereichs neu zu referenzieren, während es definiert wird. Dies liegt daran, dass diese Globals unveränderlich sein sollten, nachdem sie definiert wurden. der Code ist länger lol, das ist die kurze Version :) – argon

+0

Wenn Sie diese Liste mit dem typeOf closure zusammenführen können, so dass es wie folgt zugegriffen werden kann: 'console.log (typeOf.list)' - und if Ihr Code funktioniert auch in NodeJS, dann nehme ich ihn gerne an. Das Problem, das ich mit Ihrer aktuellen "isFunc" -Zuordnung habe, ist, dass der Vergleich nach einer Variable "item" sucht, die nicht im Umfang zu einem Zeitpunkt existiert, zu dem der "isFunc" aufgerufen wird, daher ist das auch der Grund für "bind" wie es seinen eigenen Wert enthält. – argon

+0

Gefunden einige interessante Beiträge auf "lexikalischen Umfang", wie Sie es verwendet: https://developer.mozilla.org/en/docs/Web/JavaScript/Closures und .. hier: https://spin.atomicobject.com/2014/10/20/javascript-scope-closures/.... es könnte zu Problemen führen, wenn nicht sorgfältig verwendet, aber ... hier: https://www.toptal.com/javascript/10-most-common- Javascript-Fehler – argon

Verwandte Themen