Leí esta pregunta sobre el "operador de coma" en las expresiones ( ,
) y los documentos de MDN al respecto, pero no puedo pensar en un escenario en el que sea útil.
Entonces, ¿cuándo es útil el operador de coma?
Leí esta pregunta sobre el "operador de coma" en las expresiones ( ,
) y los documentos de MDN al respecto, pero no puedo pensar en un escenario en el que sea útil.
Entonces, ¿cuándo es útil el operador de coma?
,
operador. Esa línea también es válida C#
, pero el ,
operador no existe allí.
,
no siempre es el ,
operador (y nunca es el ,
operador en C #). Por lo tanto, C # puede carecer de un ,
operador mientras se usa libremente ,
como parte de la sintaxis.
,
no se usa ampliamente (y no todas las apariciones de a ,
es el operador de coma) . Pero puede pedirlo prestado y una matriz para realizar un intercambio de variables en línea sin crear una variable temporal. Dado que desea intercambiar los valores de a
y b
, puede hacerlo a = [b][b = a,0]
. Esto coloca la corriente b
en el Array. El segundo []
es la notación de acceso a la propiedad. El índice visitada es 0
, pero no antes de asignar a
a b
, que ahora es seguro ya que b
es retenida en la matriz. el ,
nos permite hacer las múltiples expresiones en el []
.
Respuestas:
Lo siguiente probablemente no sea muy útil ya que no lo escribe usted mismo, pero un minificador puede reducir el código usando el operador de coma. Por ejemplo:
if(x){foo();return bar()}else{return 1}
se convertiría:
return x?(foo(),bar()):1
El ? :
operador se puede usar ahora, ya que el operador de coma (hasta cierto punto) permite escribir dos declaraciones como una sola declaración.
Esto es útil porque permite una compresión ordenada (39 -> 24 bytes aquí).
Me gustaría enfatizar el hecho de que la coma novar a, b
es el operador de coma porque no existe dentro de una expresión . La coma tiene un significado especial en las declaraciones . en una expresión estaría refiriéndose a las dos variables y evaluar , lo cual no es el caso de .var
a, b
b
var a, b
if (condition) var1 = val1, var2 = val2;
personalmente creo que evitar los corchetes siempre que sea posible hace que el código sea más legible.
El operador de coma le permite colocar varias expresiones en un lugar donde se espera una expresión. El valor resultante de varias expresiones separadas por una coma será el valor de la última expresión separada por comas.
Personalmente, no lo uso muy a menudo porque no hay muchas situaciones en las que se espera más de una expresión y no hay una forma menos confusa de escribir el código que usar el operador de coma. Una posibilidad interesante es al final de un for
ciclo cuando desea que se incremente más de una variable:
// j is initialized to some other value
// as the for loop executes both i and j are incremented
// because the comma operator allows two statements to be put in place of one
for (var i = 0; i < items.len; i++, j++) {
// loop code here that operates on items[i]
// and sometimes uses j to access a different array
}
Aquí puede ver que i++, j++
se puede poner en un lugar donde se permite una expresión. En este caso particular, las expresiones múltiples se utilizan para efectos secundarios, por lo que no importa que las expresiones compuestas adquieran el valor de la última, pero hay otros casos en los que eso podría realmente importar.
El operador de coma suele ser útil al escribir código funcional en Javascript.
Considere este código que escribí para un SPA hace un tiempo que tenía algo como lo siguiente
const actions = _.chain(options)
.pairs() // 1
.filter(selectActions) // 2
.map(createActionPromise) // 3
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {}) // 4
.value();
Este fue un escenario bastante complejo, pero del mundo real. Ténganme paciencia mientras les explico lo que está sucediendo y, en el proceso, defiendo el caso del operador de coma.
Desarma todas las opciones pasadas a esta función usando pairs
que se convertirá { a: 1, b: 2}
en[['a', 1], ['b', 2]]
Esta matriz de pares de propiedades se filtra según cuáles se consideran "acciones" en el sistema.
Luego, el segundo índice en la matriz se reemplaza con una función que devuelve una promesa que representa esa acción (usando map
)
Finalmente, la llamada a reduce
fusionará cada "matriz de propiedades" ( ['a', 1]
) de nuevo en un objeto final.
El resultado final es una versión transformada del options
argumento, que contiene solo las claves apropiadas y cuyos valores son consumibles por la función de llamada.
Mirando solo
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {})
Puede ver que la función de reducción comienza con un objeto de estado vacío state
, y para cada par que representa una clave y un valor, la función devuelve el mismo state
objeto después de agregar una propiedad al objeto correspondiente al par clave / valor. Debido a la sintaxis de la función de flecha de ECMAScript 2015, el cuerpo de la función es una expresión y, como resultado, el operador de coma permite una función "iteratee" concisa y útil .
Personalmente, me he encontrado con numerosos casos al escribir Javascript en un estilo más funcional con ECMAScript 2015 + Arrow Functions. Dicho esto, antes de encontrarme con las funciones de flecha (como en el momento de escribir la pregunta), nunca había usado el operador de coma de forma deliberada.
reduce
.reduce((state, [key, value]) => (state[key] = value, state), {})
. Y me doy cuenta de que esto frustra el propósito de la respuesta, pero .reduce((state, [key, value]) => Object.assign(state, { [key]: value }), {})
eliminaría por completo la necesidad del operador de coma.
Otro uso del operador de coma es ocultar los resultados que no le interesan en la respuesta o en la consola, simplemente por conveniencia.
Por ejemplo, si evalúa myVariable = aWholeLotOfText
en la réplica o la consola, imprimirá todos los datos que acaba de asignar. Estas pueden ser páginas y páginas, y si prefiere no verlas, puede evaluarlas myVariable = aWholeLotOfText, 'done'
, y la respuesta / consola simplemente imprimirá 'listo'.
Oriel señala correctamente † que las funciones personalizadas toString()
o get()
incluso podrían hacer que esto sea útil.
El operador de coma no es específico de JavaScript, está disponible en otros lenguajes como C y C ++ . Como operador binario, esto es útil cuando el primer operando, que generalmente es una expresión, tiene el efecto secundario deseado requerido por el segundo operando. Un ejemplo de wikipedia:
i = a += 2, a + b;
Obviamente, puede escribir dos líneas de códigos diferentes, pero usar la coma es otra opción y, a veces, más legible.
No estaría de acuerdo con Flanagan y diría que la coma es realmente útil y permite escribir código más legible y elegante, especialmente cuando sabes lo que estás haciendo:
Aquí está el artículo muy detallado sobre el uso de comas:
Varios ejemplos extraídos de allí para la prueba de demostración:
function renderCurve() {
for(var a = 1, b = 10; a*b; a++, b--) {
console.log(new Array(a*b).join('*'));
}
}
Un generador de fibonacci:
for (
var i=2, r=[0,1];
i<15;
r.push(r[i-1] + r[i-2]), i++
);
// 0,1,1,2,3,5,8,13,21,34,55,89,144,233,377
Encuentre el primer elemento padre, análogo de la .parent()
función jQuery :
function firstAncestor(el, tagName) {
while(el = el.parentNode, el && (el.tagName != tagName.toUpperCase()));
return el;
}
//element in http://ecma262-5.com/ELS5_HTML.htm
var a = $('Section_15.1.1.2');
firstAncestor(a, 'div'); //<div class="page">
while ((el = el.parentNode) && (el.tagName != tagName.toUpperCase()))
estaría bien en ese contexto.
No he encontrado un uso práctico aparte de eso, pero aquí hay un escenario en el que James Padolsey usa muy bien esta técnica para la detección de IE en un ciclo while:
var ie = (function(){
var undef,
v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i');
while ( // <-- notice no while body here
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
);
return v > 4 ? v : undef;
}());
Estas dos líneas deben ejecutarse:
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
Y dentro del operador de coma, ambos se evalúan aunque uno podría haberlos hecho declaraciones separadas de alguna manera.
do
- while
bucle.
Hay algo "extraño" que se puede hacer en JavaScript llamando a una función indirectamente usando el operador de coma.
Aquí hay una descripción larga: llamada de función indirecta en JavaScript
Usando esta sintaxis:
(function() {
"use strict";
var global = (function () { return this || (1,eval)("this"); })();
console.log('Global === window should be true: ', global === window);
var not_global = (function () { return this })();
console.log('not_global === window should be false: ', not_global === window);
}());
Puede obtener acceso a la variable global porque eval
funciona de manera diferente cuando se llama directamente o cuando se llama indirectamente.
He encontrado que el operador de coma es más útil al escribir ayudantes como este.
const stopPropagation = event => (event.stopPropagation(), event);
const preventDefault = event => (event.preventDefault(), event);
const both = compose(stopPropagation, preventDefault);
Puedes reemplazar la coma con una || o &&, pero luego necesitaría saber qué devuelve la función.
Más importante que eso, el separador de coma comunica la intención : al código no le importa lo que evalúe el operando izquierdo, mientras que las alternativas pueden tener otra razón para estar allí. Esto, a su vez, hace que sea más fácil de entender y refactorizar. Si el tipo de retorno de la función cambia alguna vez, el código anterior no se verá afectado.
Naturalmente, puede lograr lo mismo de otras maneras, pero no tan sucintamente. Si || y && encontraron un lugar en el uso común, al igual que el operador de coma.
tap
( ramdajs.com/docs/#tap ). Básicamente, está ejecutando un efecto secundario y luego devolviendo el valor inicial; muy útil en programación funcional :)
Un caso típico en el que termino usándolo es durante el análisis de argumentos opcional. Creo que lo hace más legible y más conciso para que el análisis de argumentos no domine el cuerpo de la función.
/**
* @param {string} [str]
* @param {object} [obj]
* @param {Date} [date]
*/
function f(str, obj, date) {
// handle optional arguments
if (typeof str !== "string") date = obj, obj = str, str = "default";
if (obj instanceof Date) date = obj, obj = {};
if (!(date instanceof Date)) date = new Date();
// ...
}
Digamos que tienes una matriz:
arr = [];
Cuando ingresa push
a esa matriz, rara vez está interesado en push
el valor de retorno, es decir, la nueva longitud de la matriz, sino más bien la matriz en sí:
arr.push('foo') // ['foo'] seems more interesting than 1
Usando el operador de coma, podemos presionar sobre la matriz, especificar la matriz como el último operando de la coma y luego usar el resultado, la matriz en sí, para una llamada posterior al método de matriz, una especie de encadenamiento:
(arr.push('bar'), arr.push('baz'), arr).sort(); // [ 'bar', 'baz', 'foo' ]
Otra área donde se puede utilizar el operador de coma es la ofuscación de código .
Digamos que un desarrollador escribe un código como este:
var foo = 'bar';
Ahora, decide ofuscar el código. La herramienta utilizada puede cambiar el código de esta manera:
var Z0b=(45,87)>(195,3)?'bar':(54,65)>(1,0)?'':'baz';// Z0b == 'bar'
Demostración: http://jsfiddle.net/uvDuE/
var i, j, k;
vsvar i; var j, var k
?