2017-05-11 30 views
2

Ich möchte diese Funktionalität erreichen:Wie man eine Eigenschaft/Methode aufrufbar macht oder nicht?

  1. ich ein Objekt var obj = {};
  2. Ich habe drei Angebote in diesem obj, obj.zero & obj.one & obj.binaryString

    • obj.zero & obj.one sind Methoden während obj.binaryString haben ist eine Zeichenfolge

Wenn ich die Eigenschaften Kette, mag ich sie ihre jeweilige Stelle nach binaryString hinzuzufügen. So zum Beispiel:

obj.one.zero.zero.one => macht obj.binaryString = 1001

obj.one.zero.one.one.zero => macht obj.binaryString = 10110

Ich habe die obige Funktionalität mit diesem erreicht:

function Binary() { 
    var obj = { binaryString: '' }; 

    Object.defineProperty(obj, 'zero', { 
     get: function() { 
      obj.binaryString += '0'; 
      return obj; 
     } 
    }); 

    Object.defineProperty(obj, 'one', { 
     get: function() { 
      obj.binaryString += '1'; 
      return obj; 
     } 
    }); 

    return obj; 
} 

var binary = new Binary(); 
binary.one.zero.zero.one // => obj.binaryString becomes '1001' 

Jetzt möchte ich Loggen Sie sich die ausgefüllten binaryString, plus und additionalString, die ich mit dem folgenden Code erreicht haben:

// placed inside Binary constructor function 
Object.defineProperty(obj, 'log', { 
    get: function() { 
     return function(additionalString) { 
      console.log(obj.binaryString + additionalString); 
     }; 
    } 
}); 

Also mit diesem aktuellen Code kann ich dies tun:

binary.one.zero.one.zero.one.log(' is the answer'); 
// logs out `10101 is the answer` 

Was ich tun möchte, ist der log loswerden und machen die one und zero Methoden aufrufbaren oder nicht, so kann ich dies erreichen Funktionalität:

binary.one.one.zero.one(' is the result') 
// => logs out `1101 is the result` 

Wie kann ich das tun?

Ich glaube, es eine ähnliche Funktionalität wie Chalk Werke wäre:

chalk.blue.bold('Hello world!'); 
// `blue` is not invoked here but it adds the color blue to the style 

chalk.blue('Hello world!'); 
// `blue` IS invoked here. It adds blue to the style and returns the stylized string 
+2

Mache 'obj' zu einer Funktion anstelle eines einfachen Objekts. Geben Sie der Funktion die Eigenschaft '.binaryString'. Wenn sie aufgerufen wird, kann die Funktion die Eigenschaft über 'this.binaryString' oder' obj.binaryString' abrufen. –

+4

... so: https://jsfiddle.net/Lbk70spw/ –

+0

Sie haben vor ein paar Stunden dieselbe Frage gestellt ... http://stackoverflow.com/questions/43902656/make-a-property-either -invokable-or-not – Badacadabra

Antwort

3

Nur Sprechen Sie die obj als Funktion und drucken, was immer Sie wollen.

function Binary() { 
 
    var obj = function(msg){ console.log(msg+this.binaryString) }; 
 
    obj.binaryString = '' 
 

 
    Object.defineProperty(obj, 'zero', { 
 
     get: function() { 
 
      obj.binaryString += '0'; 
 
      return obj; 
 
     } 
 
    }); 
 

 
    Object.defineProperty(obj, 'one', { 
 
     get: function() { 
 
      obj.binaryString += '1'; 
 
      return obj; 
 
     } 
 
    }); 
 

 
    return obj; 
 
} 
 

 
var binary = new Binary(); 
 
binary.one.zero.zero.one.zero(" is the result ")

1

Ich möchte darauf hinweisen, dass das, was Sie tun, eine sehr schlechte/gefährliche Idee ist: missbrauchen Leseeigenschaften des Objekts mutieren selbst für Ärger bittet. Du wirst es vielleicht nicht sehen, aber es wird zu Schmerzen und Herzschmerz in Form von schwer zu findenden Käfern und verworrenen Mustern führen.

Was Sie können tun, ist, das ist nicht so gefährlich ist, ist stattdessen das Objekt mutiert selbst zurückgeben eine neue Instanz von Binary mit jedem Aufruf #one oder #zero.Zum Beispiel:

function Binary(s) { 
    this.binaryString = s || '' 
} 
Object.defineProperty(Binary.prototype, 'zero', { 
    get: function() { 
    return new Binary(this.binaryString + '0') 
}}) 
Object.defineProperty(Binary.prototype, 'one', { 
    get: function() { 
    return new Binary(this.binaryString + '1') 
}}) 

Dies ist der Ansatz von Chalk, und wird viel sicherer und weniger fehleranfällig sein.

UPDATE:

Nach über Ihr Problem zu denken, und Ihre Frage zu sehen, ich denke, der beste Ansatz überhaupt gar keine Klassen zu verwenden. Sie können dieses Problem mit einem reinen funktionsbasierten Ansatz lösen. Es ist unveränderlich, es ist sicher und ich glaube, es ist weniger verwirrend. Hier ist es in ES5:

function bin(str) { 
    if(!str) str = '' 
    function f(msg) { return str + ' ' + msg } 
    return Object.defineProperties(f, { 
    zero: { 
     get: function() { 
     return bin(str + '0') 
     }, 
    }, 
    one: { 
     get: function() { 
     return bin(str + '1') 
     }, 
    }, 
    }) 
} 

Und wenn Sie ES6 verwenden können (aka ES2015), können Sie machen es viel kompakter:

function bin(str = '') { 
    return Object.defineProperties(msg => `${str} ${msg}`, { 
    zero: { get() { return bin(str + '0') } }, 
    one: { get() { return bin(str + '1') } }, 
    }) 
} 

Sie würde es so verwenden:

bin().one.zero.one.zero('is the answer') // '1010 is the answer' 
+0

danke für den Rat. Würde es Ihnen etwas ausmachen, mir zu sagen, wie mein Code zu schwer zu findenden Fehlern und verworrenen Mustern führen würde? Im Moment scheint es mir ziemlich einfach zu verstehen und zu debuggen. Ist es nur eine schlechte Übung, dies zu tun? Würde diese Funktionalität tatsächlich zu mehr Fehlern führen? Vielen Dank. Warum setzen Sie die Eigenschaften auf den "Prototyp" statt auf das Objekt selbst? – georgej

+1

Read Eigenschaften sind - wie der Name schon sagt - zum Lesen von Dingen, zumindest per Konvention (und es ist eine gute und vernünftige Konvention). Es wäre leicht zu vergessen, dass etwas, das wie eine Leseeigenschaft aussieht, tatsächlich das Objekt mutiert. Darüber hinaus ist JavaScript-Code voll von automatischer Introspektion. Wenn Sie zum Beispiel 'for (p in someBinaryNumber) console.log (someBinaryNumber [p])' sagen würden, würden Sie 1 und 0 zu Ihrer Nummer hinzufügen! Schlimmer noch, Sie konnten die Reihenfolge nicht vorhersagen! In zunehmendem Maße haben die Menschen das Gefühl, dass Mutabilität im Allgemeinen nur schlecht ist. –

+1

Um die Eigenschaften auf "Prototyp" zu setzen, ist es der "OOP" Weg, dies zu tun, obwohl dies ein so seltsames hybrides Beispiel ist, dass es sechs von einem halben Dutzend des anderen ist. Und OOP ist im Allgemeinen in JS komisch, und viele Leute denken, dass Sie es sowieso nicht tun sollten (Achselzucken). Sicherlich schreibe ich nicht viel von dem, was heutzutage als OOP gelten würde. –