2009-03-07 16 views
24

Siempre me he preguntado por qué Javascript tiene el objeto matemático global en lugar de dar a los números sus propios métodos. ¿Hay una buena razón para eso?Extendiendo el prototipo Number en javascript y el objeto Math?

También hay algún inconveniente (aparte de la eficiencia) a hacer algo como esto ?:

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

Sólo para dejar en claro, entiendo que las constantes como π necesitan en alguna parte y funciones que son aplicadas en más de una número como min/max. La pregunta fue principalmente en relación con los métodos que sólo afectan un solo número, tal como redonda, ABS, pecado, prisionero de guerra, etc.

Respuesta

16

El motivo del objeto Math es simple: "porque Java lo hace". No es la mejor de las razones, pero aquí estamos. Creo que las cosas tenían más sentido en aquel entonces, antes de que Douglas Crockford comenzara su campaña para suprimir la mitad del lenguaje *. Originalmente estabas "permitido", o quería decir, para hacer cosas como esta:

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

El inconveniente de aumentar la diferencia Number.prototype es que alguien podría hacer lo mismo. O peor, por ejemplo, defina Number.prototype.round como una función de redondeo simétrica.

Si está buscando formas de hacer su vida más fácil, ¿por qué detenerse allí? ¿Por qué no simplemente incluir las funciones Math como funciones globales?

var m = 'abs acos asin atan atan2 ceil cos exp floor log max min ' + 
     'pow random round sin sqrt tan PI').split(' '); 
for (var i=0,l=m.length; i<l; i++) { 
    window[ m[i] ] = Math[ m[i] ]; 
} 

Esto eliminará todas las funciones matemáticas en el ámbito global, lo que le permite dejar de escribir "Matemáticas". Pregúntese: ¿Hay alguna diferencia real entre extender Number y extender window con estas funciones?

* Antes de que me llame: El comentario de Crockford no debe tomarse en serio. Estoy de acuerdo con él en que with es muy peligroso en un entorno global implícito.

1

Creo matemáticas es más de conjunto de métodos numéricos. Su uso es más amplio. Digamos que usar NumberVariable.PI puede ser confuso. Lo mismo con la generación de números aleatorios.

También creo que la extensión del número está bien, porque es parte de la naturaleza de JS. Quizás alguien me corrija si me equivoco aquí.

+0

Usted puede extender casi cualquier cosa, pero el objeto Array. Es el objeto Array donde extenderse es molesto porque no se puede hacer un simpel para el ciclo de entrada (sí, sé que se puede usar un for() pero eso se ve tan feo. –

+3

@Pim Jager: no se debe usando para ... en matrices de todos modos - eso es para objetos. Por eso el * real * no-no se extiende Object.prototype ... – Shog9

+2

Puede extender si su versión de javascript admite Object.defineProperty. Existe la opción enumerable : falso – dresende

18

No hay inconveniente en que se extiende Number.prototype otro entonces confundir otras personas. ¿Cuál es el punto de? ¿Qué es mejor al usar value.round() en lugar de Math.round(value)?

Hay varias buenas razones para la Math objeto:

  1. Funciona para los no números, también: Math.round("5") obras, mientras que value.round() no funcionará cuando el valor es una cadena (por ejemplo, el valor de una cuadro de texto)
  2. Algunos miembros de la clase Math no pertenecen a un valor numérico "primaria", como Math.min() o Math.max(). ¿O quieres usarlo como a.max(b)?
  3. Otros miembros son globales y no pertenecen a un número especializado. Los ejemplos son constantes como Math.PI o la función Math.random().
+0

Buenas observaciones, +1. Me pregunto, sin embargo, por qué Douglas Crockford dijo que JavaScript cometió un error al tomar prestado el objeto Math de Java. –

+0

@Ferdinand: Nunca pensé utilizar nada como "a.max ('5 ') ". Algunas de las funciones y constantes pertenecen al objeto Math (actualizaré mi publicación para que quede claro). Las que se aplican solo al número son lo que me interesa. Que puede usar cadenas es un buen punto. – Annan

+0

También hay consideraciones de rendimiento: valor. Cualquier cosa requiere encajonar el valor, por ejemplo. convirtiendo el valor en un objeto. (Es posible evitar esto ocasionalmente, pero no en ninguno de sus posibles casos de uso) – olliej

12

trate de hacer 123.round();

Su consola Javascript arrojará unos pocos cientos de errores a los ojos: P, nah ...

Usted puede hacer:

Number.prototype.x a continuación: (123).x(); pero nunca 123.x();

+2

Siempre me he preguntado por qué no podías hacer 123.method(). Sé que es más fácil no permitirlo debido a las carrozas, sin embargo, creo que el rubí permite la sintaxis y ¡todo sería más fácil! – Annan

+14

Simple: 123..round() – dresende

+6

Sí, cualquiera '123..round()' o '(123) .round()' funcionará. '123..round() === 123.0.round()' – sam

1

Creo que llamarlo de esta manera también funciona, ya que las funciones prototipo de Number funcionan igual que las funciones prototipo de todos los objetos do:

5.5["round"](); 
//should return 6 
1

Entonces, la conversación sobre si es una buena idea o no, puede hacerlo bien.

Usted puede hacer 123.x() pero el intérprete para js se rompe (ya que no interpreta el punto como un despacho de mensajes)

Extrañamente, puede utilizar 123 .x() (con una espacio entre el número y el punto) en su lugar, y funcionará.

123..also funciona, pero eso se debe a que ha realizado efectivamente un decimal y luego despachar a ella

(typeof 123.) === 'número') // verdadera

Probar:

Number.prototype.times = function (other) {return this * other}; 3. Veces (5);

en la consola.

0

Mi opinión sobre esto es que si lo hace los controles adecuados para no sobrescribir funcionalidad nativa, nombre con el conocimiento de las normas de nomenclatura nativas y que hace que su código sea más legible y manejable, a continuación, hacer que el código cómoda y conveniente.

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

AS para el uso de este, debido a la naturaleza de JavaScript, creo que la mejor manera de hacerlo es mediante:

  • Envolver el número en una variable en lugar de un simple valor estático (más a menudo el caso)
    • nNum.round();
  • Envolver el valor sencillo estática entre paréntesis:
    • (123) .round();
  • Llamar utilizando notación de corchetes
    • 123 [ "redondo"].llamada();
Cuestiones relacionadas