2017-11-08 3 views
1

Ich bin in einer vorhandenen Bibliothek und ich bin verwirrt über die Verwendung von arithmetischen Operationen auf Objekte.Arithmetische Operationen an Objekten

Die Objekte, die für arithmetische Operationen verwendet wurden, wie folgt aussehen:

const id = { 
    _high: 0, 
    _low: 256, 
    remainder: { _low: 0, high: 0, remainder: null } 
}; 

while (id > 0) { 
    const remainder = Math.floor(id % 14); 
} 

Frage:

{ 
    _high: 0, 
    _low: 256, 
    remainder: { _low: 0, high: 0, remainder: null } 
} 

Sie haben wie diese verwendet

Was genau passiert, wenn Man wendet eine arithmetische Operation wie Modulo auf ein Objekt an oder vergleicht es mit einer Zahl?

Falls möglich, überschreiben Sie das angegebene Snippet in etwas, das die Objekteigenschaften verwendet.

+0

@NinaScholz Siehe den kommentar. Es würde ein Objekt wie das obige Beispiel zurückgeben. – kentor

+0

@NinaScholz Das ist genau meine Frage, ich verstehe es auch nicht, aber es funktioniert. Sie können es selbst testen. Ich bemerkte, dass es false zurückgab, wenn (alle?) Eigenschaften 0 sind (und null?) Und es wird true zurückgeben, wenn eine Zahl (zB: _low' höher als 0 ist) – kentor

+0

JavaScript wird versuchen, das Objekt zu konvertieren eine Zahl durch Aufruf der '.valueOf()' Methode. Das wird detailliert in der Sprachspezifikation erklärt. – Pointy

Antwort

4

You Don't Know JS: types & grammar, chapter 4:

Objects (und Arrays) wird zunächst auf ihren Grundwert Äquivalent umgewandelt werden, und der resultierende Wert (wenn ein primitiver nicht aber bereits eine Nummer) zu einer Reihe gezwungen wird entsprechend der ToNumber gerade erwähnte Regeln.

Um in diese primitive Wertäquivalent zu konvertieren, wird die ToPrimitive abstrakte Operation (ES5-Spezifikation, Abschnitt 9.1) den fraglichen Wert konsultieren (unter Verwendung der internen DefaultValue-Operation-ES5-Spezifikation, Abschnitt 8.12.8), um zu sehen, ob es a hat valueOf() -Methode. Wenn valueOf() verfügbar ist und einen primitiven Wert zurückgibt, wird dieser Wert für die Nötigung verwendet. Wenn nicht, liefert toString() den Wert für die Nötigung, falls vorhanden.

Wenn keine der beiden Operationen einen primitiven Wert bereitstellen kann, wird ein TypeError ausgelöst.


Also, ich gehe davon aus, dass das Objekt ein valueOf Methode hat, die eine Zahl zurückgibt, so in beiden arithmetischen Operationen, die Sie auf Ihrem Objekt durchführen, diese Methode aufgerufen wird, um das Objekt in eine Reihe zu zwingen, und der resultierende Wert ist, was tatsächlich in der Operation verwendet wird.


Auch Ihr Beispiel ziemlich nutzlos ist, da es nicht, dass die zugrunde liegenden valueOf Verfahren nicht enthalten, wenn wir versuchen, so etwas wie id + 10 zu tun, wir [object Object]10 bekommen, warum ist das so? Der Standardwert valueOf ist nicht in der Lage, ein Grundelement bereitzustellen, also wird toString abgefragt, das [object Object] zurückgibt. Dieser Grundelementwert wird dann mit 10 verkettet, was zu [object Object]10 führt.

Um dies besser zu verstehen, einen Blick auf diese Beispiele nehmen:

1.

const id = { 
_high: 0, 
_low: 256, 
remainder: { _low: 0, high: 0, remainder: null }, 
valueOf: function(){ 
return 20; /* valueOf does not fail to provide a primitive, "20" will 
be used". */ 
}, 
toString: function() { 
return 10; /* toString's return value would be used (if it was a primitive), if "valueOf" failed to provide a primitive. */ 
} 
}; 


console.log(id + 10); // prints out "30" 


2.

const id = { 
_high: 0, 
_low: 256, 
remainder: { _low: 0, high: 0, remainder: null }, 
valueOf: function(){ 
return {}; // valueOf fails to provide a primitive 
}, 
toString: function() { 
return 10; // toString provides a primitive value, so "10" will be used. 
} 
}; 


console.log(id + 10); // prints out "20" 


3.

const id = { 
_high: 0, 
_low: 256, 
remainder: { _low: 0, high: 0, remainder: null }, 
valueOf: function(){ 
return {}; /* valueOf fails to provide a primitive */ 
}, 
toString: function() { 
return {}; /* toString fails to provide a primitive as well */ 
} 
}; 


console.log(id + 10); // a "TypeError" is thrown :(
1

Antwort: Methode .valueOf() heißt Sie können dort Ihre eigene Logik implementieren.

var obj = { 
 
a: 11, 
 
b: 30, 
 
valueOf: function() { 
 
    return this.a + this.b; 
 
} 
 
} 
 

 
if (obj> 40) { 
 
    alert(obj + 1); 
 
}

+0

aber im Allgemeinen ist eine schlechte Idee, Ihren Fluss basierend auf Casting-Objekt zu String oder eine Zahl zu bauen; viel besser ist es, entsprechende Logik zu einigen gut benannten Methoden wie 'if (obj.isStillAlive()) zu bewegen ... ' – skyboyer

+0

Ich stimme zu, aber es muss auch ein Vorteil sein? etwas, das den Nachteil von Verwirrungen wie OPs ausgleicht. – Taurus

+0

@Taurus sehe keine. Es ist immer verwirrend, dass das neue Date() + 1000 die Nummer und nicht das Date-Objekt zurückgibt. Es könnte hilfreich sein, wenn die Standardlogik von Array.prototype.sort() .valueOf() anstelle von .toString() verwendet, um Elemente zu vergleichen. Aber leider ist es nicht (sagen wir, Array von Datum ist nach String-Darstellung sortiert - so dass alle Freitage zuerst und alle Mittwochs dauern) – skyboyer

Verwandte Themen