2009-03-07 16 views
24

Ich habe mich immer gefragt, warum Javascript das globale Math-Objekt hat, anstatt Zahlen ihre eigenen Methoden zu geben. Gibt es einen guten Grund dafür?Erweitern Sie Number.prototype in Javascript und das Math-Objekt?

Auch gibt es irgendwelche Nachteile (außer Effizienz), so etwas zu tun ?:

Number.prototype.round = function(){ 
    return Math.round(this); 
}; 

Nur klar zu machen, ich verstehe, dass Konstanten wie π müssen irgendwo und Funktionen, die auf mehr als einem angewendet werden Nummer wie min/max. Die Frage bezog sich hauptsächlich auf Methoden, die nur eine einzige Zahl betreffen, wie rund, abs, sin, pow, usw.

Antwort

16

Der Grund für das Objekt Math ist einfach: "weil Java es tut". Nicht die besten Gründe, aber hier sind wir. Ich denke, dass die Dinge damals mehr Sinn machten, bevor Douglas Crockford seine Kampagne begann, die halbe Sprache zu unterdrücken *. Ursprünglich waren Sie „erlaubt“ oder gemeint, solche Dinge zu tun:

with (Math) { 
    var n = min(round(a) * round(b), sqrt(c)); 
    var result = exp(n + d); 
} 

Der Nachteil Number.prototype erstreckt, ist, dass jemand anderes könnte das gleiche tun. Oder schlimmer, zum Beispiel definieren Number.prototype.round als eine symmetrische Rundungsfunktion.

Wenn Sie nach Möglichkeiten suchen, Ihr Leben einfacher zu machen, warum dann aufhören? Warum nicht einfach Math Funktionen als globale Funktionen?

Dadurch werden alle mathematischen Funktionen in den globalen Bereich verschoben, sodass Sie effektiv aufhören können, "Math" einzugeben. Fragen Sie sich selbst: Gibt es einen wirklichen Unterschied zwischen der Erweiterung Number und der Erweiterung window mit diesen Funktionen?

* Bevor Sie mich flammen: Der Crockford-Kommentar ist nicht ernst zu nehmen. Ich stimme ihm zu, dass with in einer impliziten globalen Umgebung sehr gefährlich ist.

1

Ich denke, Mathematik ist mehr als ein Satz von Zahlenmethoden. Es ist breiter einsetzbar. Nehmen wir an, die Verwendung von NumberVariable.PI kann verwirrend sein. Gleiches mit der Erzeugung von Zufallszahlen.

Auch ich denke, die Erweiterung Nummer ist in Ordnung, weil es der Teil von JS Natur ist. Vielleicht korrigiert mich jemand, wenn ich hier falsch liege.

+0

tun. Es ist das Array-Objekt, wo das Erweitern nervig ist, weil man dann kein Simple für..in der Schleife machen kann (ja, ich weiß, dass man for for verwenden kann), aber das sieht einfach hässlich aus. –

+3

@Pim Jager: Das sollte nicht sein die Verwendung von for ... in für Arrays sowieso - das ist für Objekte gedacht.Das ist der Grund, warum die * real * no-no erweitert Object.prototype ... – Shog9

+2

Sie können erweitern, wenn Ihre Javascript-Version Object.defineProperty unterstützt.Es gibt die Option aufzählbar : falsch – dresende

18

Es gibt keinen Nachteil bei der Erweiterung Number.prototype andere dann verwirrend andere Leute. Was ist der Punkt? Was ist besser in der Verwendung von value.round() anstelle von Math.round(value)?

Es gibt mehrere gute Gründe für die Math Objekt:

  1. Es funktioniert für Nicht-Zahlen, auch: Math.round("5") Arbeiten während value.round() wird nicht funktionieren, wenn der Wert ein String ist (zum Beispiel, der Wert von a Textfeld)
  2. Einige Elemente des Math-Objekts gehören nicht zu einem "primären" Zahlenwert, wie Math.min() oder Math.max(). Oder möchten Sie es wie a.max(b) verwenden?
  3. Andere Mitglieder sind global und gehören keiner spezialisierten Nummer an. Beispiele sind Konstanten wie Math.PI oder die Funktion Math.random().
+0

Gute Beobachtungen, +1 Ich frage mich aber, warum Douglas Crockford sagte, dass JavaScript einen Fehler gemacht hat, wenn er das Math-Objekt aus Java ausgeliehen hat: –

+0

@Ferdinand: Ich hatte nie vor etwas wie "a.max ('5 ') ". Einige der Funktionen und Konstanten gehören in das Math-Objekt (ich aktualisiere meinen Beitrag, um das zu verdeutlichen). Die, die nur auf die Zahl angewendet werden, interessiert mich. Das können Sie Strings verwenden ist ein guter Punkt, aber – Annan

+0

Es gibt auch Leistungsaspekte - value.anything erfordert Boxen den Wert - zB. Wert in ein Objekt umwandeln. (Es ist möglich, dies gelegentlich zu vermeiden, aber nicht in irgendeinem Ihrer wahrscheinlichen Anwendungsfälle) – olliej

12

Try 123.round();

Ihre Javascript-Konsole tun ein paar hundert von Fehlern in die Augen werfen: P, nah ...

Sie tun können:

Number.prototype.x dann: (123).x(); aber nie 123.x();

+2

Ich habe mich immer gefragt, warum Sie 123.method() nicht tun können. Ich weiß, dass es leichter ist, es wegen der Floats nicht zuzulassen, aber ich denke Ruby erlaubt die Syntax und es würde alles einfacher machen! – Annan

+14

Einfach: 123..round() – dresende

+6

Ja, entweder '123..round()' oder '(123) .round()' funktionieren. '123..round() === 123.0.round()' – sam

1

Ich glaube, es funktioniert so gut, da Numbers Prototyp-Funktionen genauso funktionieren wie die Prototyp-Funktionen jedes anderen Objekts:

1

Also, das Gespräch darüber, ob es eine gute Idee ist oder nicht beiseite, können Sie das gut tun.

können Sie tun 123.x(), aber der Dolmetscher für js gebrochen

Weirdly (da sie nicht den Punkt als Botschaftsabsendung interpretiert), können Sie 123 .x() verwenden (mit einem Abstand zwischen der Zahl und dem Punkt), und es wird funktionieren.

123..also aber das funktioniert, weil Sie effektiv eine Dezimalzahl gemacht haben und dann, um es Dispatching

(typeof 123) === 'Zahl') // true

Versuchen:

Number.prototype.times = Funktion (andere) {return this * Other}; 3 × (5);

in der Konsole.

0

Meine Sicht auf das ist, dass, wenn Sie die richtigen Überprüfungen durchführen, um native Funktionalität nicht zu überschreiben, Name mit Verständnis der nativen Benennungsstandards und macht Ihren Code lesbarer und überschaubar, dann machen Sie Ihren Code bequem und bequem.

if (Number.prototype.round == null) 
    Number.prototype.round = function() { return Math.round(this); } 

da dies für die Nutzung, die aufgrund der Art von JavaScript, glaube ich, der beste Weg, dies zu tun ist durch:

  • die Zahl in einer Variablen anstelle eines einfachen statischen Wert Wrapping (Most oft der Fall)
    • nNum.round();
  • den einfachen statischen Wert in Klammern Bewicklung:
    • (123) .round();
  • eckige Klammer-Notation
    • 123 [ "rund"] Aufruf verwenden.Anruf();
Verwandte Themen