numero - libro javascript pdf español
¿Por qué evitar los operadores de incremento("++") y decremento("-") en JavaScript? (17)
¿Es Fortran un lenguaje parecido a C? No tiene ni ++ ni -. Aquí es cómo se escribe un bucle :
integer i, n, sum
sum = 0
do 10 i = 1, n
sum = sum + i
write(*,*) ''i ='', i
write(*,*) ''sum ='', sum
10 continue
El elemento de índice i es incrementado por las reglas del lenguaje cada vez que pasa por el bucle. Si desea aumentar en algo distinto de 1, cuente hacia atrás con dos, por ejemplo, la sintaxis es ...
integer i
do 20 i = 10, 1, -2
write(*,*) ''i ='', i
20 continue
¿Python C-like? Utiliza las comprensiones de rango y lista y otras sintaxis para evitar la necesidad de incrementar un índice:
print range(10,1,-2) # prints [10,8.6.4.2]
[x*x for x in range(1,10)] # returns [1,4,9,16 ... ]
Por lo tanto, basándose en esta exploración rudimentaria de exactamente dos alternativas, los diseñadores de idiomas pueden evitar ++ y - al anticipar casos de uso y proporcionar una sintaxis alternativa.
¿Son Fortran y Python mucho menos un imán de errores que los lenguajes de procedimiento que tienen ++ y -? No tengo pruebas.
Afirmo que Fortran y Python son como C porque nunca he conocido a alguien con fluidez en C que no pudiera, con el 90% de precisión, adivinar correctamente la intención de Fortran o Python no ofuscados.
Uno de los consejos para la herramienta jslint es:
++ y -
Se sabe que los operadores ++ (incremento) y - (decremento) contribuyen al código incorrecto al fomentar el engaño excesivo. Solo son superados por la arquitectura defectuosa en la habilitación de virus y otras amenazas de seguridad. Hay una opción plusplus que prohíbe el uso de estos operadores.
Sé que las construcciones de PHP como $foo[$bar++]
pueden resultar fácilmente con errores off-by-one, pero no pude encontrar una mejor manera de controlar el bucle que un while( a < 10 ) do { /* foo */ a++; }
while( a < 10 ) do { /* foo */ a++; }
o for (var i=0; i<10; i++) { /* foo */ }
.
¿Está resaltando jslint porque hay algunos lenguajes similares que carecen de la sintaxis " ++
" y " --
" o lo manejan de manera diferente, o existen otras razones para evitar " ++
" y " --
" que me pueden faltar? ?
Como se mencionó en algunas de las respuestas existentes (de las que, de manera molesta, no puedo hacer comentarios), el problema es que x ++ ++ x evalúa a diferentes valores (antes vs después del incremento), lo cual no es obvio y puede ser muy confuso. si ese valor es usado cdmckay sugiere muy sabiamente permitir el uso del operador de incremento, pero solo de una manera que no se use el valor devuelto, por ejemplo, en su propia línea. También incluiría el uso estándar dentro de un bucle for (pero solo en la tercera declaración, cuyo valor de retorno no se usa). No puedo pensar en otro ejemplo. Habiendo sido "quemado" yo mismo, recomendaría la misma guía para otros idiomas también.
No estoy de acuerdo con la afirmación de que este exceso de rigor se debe a que muchos programadores de JS carecen de experiencia. Este es el tipo exacto de escritura típico de los programadores "demasiado inteligentes", y estoy seguro de que es mucho más común en los lenguajes más tradicionales y con los desarrolladores de JS que tienen experiencia en dichos lenguajes.
Considere el siguiente código
int a[10];
a[0] = 0;
a[1] = 0;
a[2] = 0;
a[3] = 0;
int i = 0;
a[i++] = i++;
a[i++] = i++;
a[i++] = i++;
ya que i ++ se evalúa dos veces, el resultado es (del depurador de vs2005)
[0] 0 int
[1] 0 int
[2] 2 int
[3] 0 int
[4] 4 int
Ahora considere el siguiente código:
int a[10];
a[0] = 0;
a[1] = 0;
a[2] = 0;
a[3] = 0;
int i = 0;
a[++i] = ++i;
a[++i] = ++i;
a[++i] = ++i;
Observe que la salida es la misma. Ahora puedes pensar que ++ i y i ++ son lo mismo. Ellos no son
[0] 0 int
[1] 0 int
[2] 2 int
[3] 0 int
[4] 4 int
Finalmente considere este código
int a[10];
a[0] = 0;
a[1] = 0;
a[2] = 0;
a[3] = 0;
int i = 0;
a[++i] = i++;
a[++i] = i++;
a[++i] = i++;
La salida es ahora:
[0] 0 int
[1] 1 int
[2] 0 int
[3] 3 int
[4] 0 int
[5] 5 int
Así que no son lo mismo, mezclar ambos resulta en un comportamiento no tan intuitivo. Creo que para los bucles están bien con ++, pero tenga cuidado cuando tenga varios símbolos ++ en la misma línea o la misma instrucción
Creo que los programadores deben ser competentes en el lenguaje que están usando; utilízalo claramente y utilízalo bien. No creo que deban dañar artificialmente el lenguaje que están usando. Hablo por experiencia. Una vez trabajé literalmente al lado de una tienda de Cobol donde no usaban ELSE ''porque era demasiado complicado''. Reductio ad absurdam.
En mi experiencia, ++ i o i ++ nunca ha causado más confusión que cuando aprendí por primera vez cómo funciona el operador. Es esencial para lo más básico para los bucles y para los que se imparten en cualquier escuela secundaria o curso universitario impartido en idiomas en los que pueda utilizar el operador. Personalmente encuentro que hacer algo como lo que se muestra a continuación para ver y leer mejor que algo con a ++ en una línea separada.
while ( a < 10 ){
array[a++] = val
}
Al final, es una preferencia de estilo y no nada más, lo que es más importante es que cuando haces esto en tu código permaneces coherente para que otros que trabajen en el mismo código puedan seguir y no tengan que procesar la misma funcionalidad de diferentes maneras. .
Además, Crockford parece usar i- = 1, lo que me parece más difícil de leer que --i o i--
En mi opinión, "Explícito siempre es mejor que implícito". Porque en algún momento, puede confundirse con esta declaración de incrementos y+ = x++ + ++y
. Un buen programador siempre hace que su código sea más legible.
En un bucle es inofensivo, pero en una declaración de asignación puede conducir a resultados inesperados:
var x = 5;
var y = x++; // y is now 5 and x is 6
var z = ++x; // z is now 7 and x is 7
Whitespace entre la variable y el operador también puede llevar a resultados inesperados:
a = b = c = 1; a ++ ; b -- ; c; console.log(''a:'', a, ''b:'', b, ''c:'', c)
En un cierre, los resultados inesperados también pueden ser un problema:
var foobar = function(i){var count = count || i; return function(){return count++;}}
baz = foobar(1);
baz(); //1
baz(); //2
var alphabeta = function(i){var count = count || i; return function(){return ++count;}}
omega = alphabeta(1);
omega(); //2
omega(); //3
Y activa la inserción automática de punto y coma después de una nueva línea:
var foo = 1, bar = 2, baz = 3, alpha = 4, beta = 5, delta = alpha
++beta; //delta is 4, alpha is 4, beta is 6
La confusión preincremento / postincremento puede producir errores off-by-one que son extremadamente difíciles de diagnosticar. Afortunadamente, también son completamente innecesarios. Hay mejores maneras de agregar 1 a una variable.
Referencias
Estoy francamente confundido por ese consejo. Una parte de mí se pregunta si tiene más que ver con la falta de experiencia (percibida o real) con los codificadores de JavaScript.
Puedo ver cómo alguien que simplemente "piratea" un código de muestra podría cometer un error inocente con ++ y -, pero no veo por qué un profesional experimentado los evitaría.
Hay una historia en C de hacer cosas como:
while (*a++ = *b++);
para copiar una cadena, quizás esta sea la fuente de los engaños excesivos a los que se refiere.
Y siempre está la pregunta de qué.
++i = i++;
o
i = i++ + ++i;
en realidad hacer Se define en algunos idiomas y en otros no hay garantía de lo que sucederá.
Dejando de lado esos ejemplos, no creo que haya nada más idiomático que un bucle for que use ++
para incrementar. En algunos casos, podría salirse con un bucle foreach, o un bucle while que verificó una condición diferente. Pero contorting su código para tratar de evitar el uso incremental es ridículo.
He estado viendo el video de Douglas Crockford sobre esto y su explicación para no usar incrementos y decrementos es que
- Se ha utilizado en el pasado en otros idiomas para romper los límites de los arreglos y causar todo tipo de maldad y maldad.
- Que sea más confuso e inexperto los desarrolladores de JS no saben exactamente lo que hace.
En primer lugar, los arreglos en JavaScript tienen un tamaño dinámico y, por lo tanto, perdóneme si me equivoco, no es posible romper los límites de un arreglo y acceder a datos a los que no debería accederse utilizando este método en JavaScript.
En segundo lugar, si debemos evitar las cosas que son complicadas, seguramente el problema no es que tengamos esta facilidad, sino que ¿hay desarrolladores que dicen hacer JavaScript pero no saben cómo funcionan estos operadores? Es bastante simple. valor ++, dame el valor actual y, después de la expresión, agrega uno a él, ++ valor, incrementa el valor antes de dármelo.
Expresiones como a ++ + ++ b son fáciles de resolver si solo recuerdas lo anterior.
var a = 1, b = 1, c;
c = a ++ + ++ b;
// c = 1 + 2 = 3;
// a = 2 (equals two after the expression is finished);
// b = 2;
Supongo que solo tienes que recordar quién tiene que leer el código; si tienes un equipo que conoce a JS de adentro hacia afuera, entonces no debes preocuparte. Si no, coméntelo, escríbalo de manera diferente, etc. Haga lo que tenga que hacer. No creo que el incremento y la disminución sean intrínsecamente malos, generen errores o creen vulnerabilidades, tal vez sean menos legibles, dependiendo de su audiencia.
Por cierto, creo que Douglas Crockford es una leyenda de todos modos, pero creo que ha causado mucho miedo a un operador que no se lo merecía.
Vivo para demostrar que estoy equivocado ...
La naturaleza "pre" y "post" de los operadores de incremento y decremento puede ser confusa para quienes no están familiarizados con ellos; Esa es una forma en que pueden ser difíciles.
La razón más importante para evitar ++ o - es que los operadores devuelven valores y causan efectos secundarios al mismo tiempo, lo que hace que sea más difícil razonar sobre el código.
Por el bien de la eficiencia, prefiero:
- ++ i cuando no se usa el valor de retorno (no temporal)
- i ++ cuando se usa el valor de retorno (sin bloqueo de la tubería)
Soy un fanático del Sr. Crockford, pero en este caso tengo que estar en desacuerdo. ++i
es un 25% menos de texto para analizar que i+=1
y posiblemente más claro.
Mi 2cents es que deben evitarse en dos casos:
1) Cuando tienes una variable que se usa en muchas filas y la aumentas / disminuyes en la primera declaración que la usa (o la última, o, peor aún, en el medio):
// It''s Java, but applies to Js too
vi = list.get ( ++i );
vi1 = list.get ( i + 1 )
out.println ( "Processing values: " + vi + ", " + vi1 )
if ( i < list.size () - 1 ) ...
En ejemplos como este, puede perder fácilmente que la variable se incremente / disminuya automáticamente o incluso elimine la primera declaración. En otras palabras, utilícelo solo en bloques muy cortos o donde la variable aparezca en el bloque en solo un par de declaraciones cerradas.
2) En caso de múltiples ++ y - aproximadamente la misma variable en la misma declaración. Es muy difícil recordar lo que sucede en casos como este:
result = ( ++x - --x ) * x++;
Los exámenes y las pruebas profesionales preguntan sobre ejemplos como los anteriores y, de hecho, me he topado con esta pregunta mientras buscaba documentación sobre uno de ellos, pero en la vida real no se debe obligar a pensar tanto sobre una sola línea de código.
Mi punto de vista es usar siempre ++ y - solos en una sola línea, como en:
i++;
array[i] = foo;
en lugar de
array[++i] = foo;
Cualquier cosa más allá de eso puede ser confusa para algunos programadores y simplemente no vale la pena en mi opinión. Los bucles son una excepción, ya que el uso del operador de incremento es idiomático y, por lo tanto, siempre claro.
No sé si esto fue parte de su razonamiento, pero si utiliza un programa de minificación mal escrito, podría convertir x++ + y
en x+++y
. Pero, de nuevo, una herramienta mal escrita puede causar todo tipo de estragos.
Otro ejemplo, más simple que algunos otros con simple retorno de valor incrementado:
function testIncrement1(x) {
return x++;
}
function testIncrement2(x) {
return ++x;
}
function testIncrement3(x) {
return x += 1;
}
console.log(testIncrement1(0)); // 0
console.log(testIncrement2(0)); // 1
console.log(testIncrement3(0)); // 1
Como puede ver, no se debe utilizar ningún incremento / decremento posterior en la declaración de devolución, si desea que este operador influya en el resultado. Pero el retorno no "atrapa" a los operadores posteriores al incremento / decremento:
function closureIncrementTest() {
var x = 0;
function postIncrementX() {
return x++;
}
var y = postIncrementX();
console.log(x); // 1
}
Si lees JavaScript Las partes buenas, verás que el reemplazo de Crockford para i ++ en un bucle for es i + = 1 (no i = i + 1). Eso es bastante limpio y legible, y es menos probable que se convierta en algo "complicado".
Crockford hizo que anular el autoincrement y el autodecrement sea una opción en jsLint. Usted elige si seguir los consejos o no.
Mi regla personal es no hacer nada combinado con autoincremento o autodecremento.
He aprendido por años de experiencia en C que no obtengo sobrecargas de búfer (o índice de matriz fuera de los límites) si sigo utilizándolo de manera simple. Pero descubrí que si tengo un exceso de búfer si caigo en la práctica "excesivamente difícil" de hacer otras cosas en la misma frase.
Por lo tanto, para mis propias reglas, el uso de i ++ como el incremento en un bucle for está bien.