El mejor azúcar sintáctico de javascript

81

Aquí tienes algunas gemas:

Literales:

var obj = {}; // Object literal, equivalent to var obj = new Object();
var arr = []; // Array literal, equivalent to var arr = new Array();
var regex = /something/; // Regular expression literal, equivalent to var regex = new RegExp('something');

Valores predeterminados:

arg = arg || 'default'; // if arg evaluates to false, use 'default', which is the same as:
arg = !!arg ? arg : 'default';

Por supuesto, conocemos funciones anónimas, pero poder tratarlas como literales y ejecutarlas en el acto (como un cierre) es genial:

(function() { ... })(); // Creates an anonymous function and executes it

Pregunta: ¿Qué otro gran azúcar sintáctico está disponible en javascript?

párpados
fuente
2
No estaba al tanto de eso || sintaxis del valor predeterminado. Agradable y compacto, aunque no tan intuitivo. (Quizás lo he visto, pero nunca lo he entendido.)
Chris Noe
1
Me costó mucho más comprender la sintaxis ternaria. Parecerá una segunda naturaleza después de escribirlo varias veces. En cuanto a los lugares en los que puede haberlo visto, creo que tanto jquery.js como prototype.js lo usan.
párpados
1
¿Qué tal explicar cada uno de los ejemplos?
pc1oad1etter
2
No sabía nada de "arg || 'predeterminado'". Esperaría que devolviera un valor booleano, ¡pero devuelve el primer valor (desde la izquierda) que se evalúa como verdadero (similar a python)! ¡Es mucho mejor que "arg = arg? Arg: 'default'"!
Jamol
¡Chris Noe empeñó este hilo!
Mahesh Velaga

Respuestas:

58

Obtener la fecha y hora actual en milisegundos:

Date.now()

Por ejemplo, para cronometrar la ejecución de una sección de código:

var start = Date.now();
// some code
alert((Date.now() - start) + " ms elapsed");
Chris Noe
fuente
Este es, de hecho, el mejor azúcar sintáctico de JavaScript. Un winnar si yuo.
párpados
3
OrbMan, eso probablemente depende del contexto; si lo pasa como un argumento, puede ser coaccionado a un Objeto en lugar de a un Número o una Cadena, en cuyo caso el + ya lo habría coaccionado a un Número. De hecho, + parece funcionar como una abreviatura de parseInt (valor, 10).
párpados
Corrección: tiene alguna diferencia con parseInt (valor, 10). Por ejemplo, + [3] y parseInt ([3], 10) son ambos iguales al número 3, pero + [3, 4] == NaN y parseInt ([3, 4], 10) == 3.
eyelidlessness
Er ... todas esas instancias de parseInt (valor, 10) deberían ser parseFloat (valor). Y Chris Noe, perdón por el spam de comentarios;)
eyelidlessness
1
Mi curiosidad me empujó a probarlo en jsperf y parece que el más eficaz es el canónico getTime () :) (ref. Jsperf.com/millisecondsdate )
sirLisko
33

Prueba de pertenencia a objetos:

var props = {a: 1, b: 2};

("a" en accesorios) // verdadero
("b" en accesorios) // verdadero
("c" en accesorios) // falso
Chris Noe
fuente
Eso es ciertamente más conciso que props.a === undefined Gracias.
párpados
15
Y es cierto incluso si props = {a: undefined}.
Ephemient
FYI: Firefox arroja un TypeError cuando intentas usar "in" en un objeto XPCNativeWrapper. Y a partir de Firefox 4, se envuelven muchos objetos. Así que volvamos a props.a === undefined en esos casos.
Chris Noe
26

En Mozilla (y según se informa IE7) puede crear una constante XML usando:

var xml = <elem> </elem>;

También puede sustituir variables:

var elem = "html";
var text = "Algún texto";
var xml = <{elem}> {texto} </ {elem}>;
Chris Noe
fuente
De Verdad? ¿Hay otros motores que lo admitan?
párpados
1
Me pregunto: ¿qué puede hacer con esa variable "xml" una vez que la haya creado? Simplemente jugando con él ahora en Firebug, parece que no tiene ningún método o propiedad y no puede agregarlo al DOM.
nickf
8
Los literales E4X son un desastre de seguridad debido a los ataques de inclusión de scripts entre sitios, y en realidad no son mucho mejores que simplemente poder decir “var xml = new XML ('<elem> </elem>')” IMO.
Bobince
2
@CharlieSomerville Ese no es el riesgo. E4X potencialmente convierte archivos ML "seguros" [X] [HT] en JS activo. Lea code.google.com/p/doctype/wiki/ArticleE4XSecurity para conocer los antecedentes de este problema.
Bobince
26

Usando funciones anónimas y un cierre para crear una variable privada (ocultación de información) y los métodos asociados get / set:

var getter, setter;

(function()
{
   var _privateVar=123;
   getter = function() { return _privateVar; };
   setter = function(v) { _privateVar = v; };
})()
Ceniza
fuente
me tomó un momento, pero lo entendí. esto ES genial.
Matt Lohkamp
Descubrí una técnica similar hace un tiempo mientras miraba a través de la fuente swfobject. Usar cierres para crear variables / métodos privados es algo en lo que probablemente nunca hubiera pensado. Es algo genial.
Herms
Con la nueva versión de JS, podemos usar el más simpleif(true) { let _privateVar=123; }
Kulvar
Tenga en cuenta el problema del potencial estilístico de las "bolas de perro" aquí. Ver: twitter.com/paul_irish/status/176187448420864000?lang=en
Jonathan.Brink
22

Ser capaz de extender los tipos de JavaScript nativos a través de la herencia de prototipos.

String.prototype.isNullOrEmpty = function(input) {
    return input === null || input.length === 0;
}
steve_c
fuente
6
Simplemente evite hacer esto en Array: stackoverflow.com/questions/61088/…
Chris Noe
Esto es cierto, pero solo si usa el bucle for (a en b). Normalmente uso marcos, como estoy seguro de que todos los demás lo hacen. Como consecuencia, normalmente uso .each ()
steve_c
Es un problema potencial si algún código en su contenedor se usa para (a en b). Y cuando ese contenedor es un navegador, podría estar rompiendo otro código en su navegador (por ejemplo, ese marco). Me ha golpeado el uno.
Chris Noe
Sí. Buenos puntos, Chris. Sigo contando la herencia de prototipos como una de las mejores características de JavaScript :)
steve_c
for (var i in obj) {if (! obj.hasOwnProperty (i)) {continuar; } ...}
eyelidlessness
21

Úselo ===para comparar valor y tipo:

var i = 0;
var s = "0";

si (i == s) // verdadero

si (i === s) // falso
Chris Noe
fuente
En realidad, se lo denomina estrictamente igual; básicamente, evita todas las conversiones de tipo que de otra manera tendrían que ocurrir al hacer ==
olliej
otros lenguajes (PHP) también lo llaman comprobación de "identidad", es decir: ¿son estos dos valores idénticos ?
nickf
@nickf, es un nombre poco apropiado. $var1 = 'string'; $var2 = 'string'; $var1 === $var2; // true, aunque $var1y $var2no son idénticos (referencias al mismo valor almacenado en la memoria), solo el mismo tipo y el mismo valor.
párpados
@eyelidlessness, no estoy seguro de que javascript funcione de esa manera ... las cadenas (generalmente) se almacenan y pasan por valor. Sin embargo los objetos se almacenan como referencia: var1 = {a : 'b'}; var2 = {a : 'b'}; var1 === var2 // false.
nickf
@nickf, lo entiendo. Pero puede eliminar el sigilo en el código PHP y obtener el mismo resultado en JavaScript. Esas cadenas no son idénticas , pero sus valores sí lo son.
párpados
21

Cuerdas multilínea:

var str = "Esto es \
todos uno \
cuerda.";

Dado que no puede sangrar las líneas siguientes sin agregar también el espacio en blanco a la cadena, la gente generalmente prefiere concatenar con el operador más. Pero esto proporciona una buena capacidad de documento aquí .

Chris Noe
fuente
2
Advertencia justa: se lanzará una excepción si hay espacios al final después de \ 's.
Daniel Szabo
21

Cambiar el tamaño de la longitud de una matriz

La propiedad length no es de solo lectura . Puede usarlo para aumentar o disminuir el tamaño de una matriz.

var myArray = [1,2,3];
myArray.length // 3 elements.
myArray.length = 2; //Deletes the last element.
myArray.length = 20 // Adds 18 elements to the array; the elements have the empty value. A sparse array.
pramodc84
fuente
1
Señor, esta debe ser la respuesta más importante sobre SO, creo. No más pushpara mí, jeje. Gracias un montón.
aefxx
4
en realidad, los elementos creados de esta manera no existen en realidad (tampoco tienen el valor indefinido, pero acceder a ellos lo hará indefinido). Tampoco puede iterar sobre ellos con for..in.
yorick
16

Repetir una cadena como "-" una cantidad específica de veces aprovechando el método de unión en una matriz vacía:

var s = new Array(repeat+1).join("-");

Resultados en "---" cuando se repite == 3.

J c
fuente
15

Al igual que el operador por defecto, ||es el operador de guardia, &&.

answer = obj && obj.property

Opuesto a

if (obj) {
    answer = obj.property;
}
else {
    answer = null;
}
Skilldrick
fuente
1
No necesariamente tiene que ser así null. Este es solo el caso cuando obj === null.
pimvdb
1
También se puede utilizar junto con || para garantizar una copia de seguridad en el caso de que obj no exista en absoluto O el objeto exista pero la propiedad clave no. De esta manera la respuesta siempre se define: answer = (obj && obj.property) || 'backupprop';
Dtipson
13
var tags = {
    name: "Jack",
    location: "USA"
};

"Name: {name}<br>From {location}".replace(/\{(.*?)\}/gim, function(all, match){
    return tags[match];
});

la devolución de llamada para el reemplazo de cadenas es útil.

Serkan Yersen
fuente
12

Getters y setters :

function Foo(bar)
{
    this._bar = bar;
}

Foo.prototype =
{
    get bar()
    {
        return this._bar;
    },

    set bar(bar)
    {
        this._bar = bar.toUpperCase();
    }
};

Nos da:

>>> var myFoo = new Foo("bar");
>>> myFoo.bar
"BAR"
>>> myFoo.bar = "Baz";
>>> myFoo.bar
"BAZ"
Jonny Buchanan
fuente
Sí, será un poco mejor que el enfoque actual que utilicé.
Ash
@eyelidlessness está en Object.defineProperty de ECMAScript 5 que IE implementa y otros navegadores pueden usar defineGetter .
Eli Gray
IE8 sólo implementos getters / setters de objetos DOM, por lo que es inútil cuando se trata de tomar sus propias APIs objeto más ordenado: - /
Jonny Buchanan
5

Esto no es exclusivo de JavaScript, pero guarda como tres líneas de código:

check ? value1 : value2
levik
fuente
¿Existe un equivalente a esto cuando no se asigna un valor (por ejemplo, fnName? FnName: defaultFn;)?
párpados
1
No, el operador ternario es estrictamente para expresiones; sin declaraciones
Josh Hinman
1
puede usarlo para evaluar funciones anónimas, como esta: "var myFunc = (browserIsIE? function () {...}: function () {...})". personalmente, no lo recomendaría ya que es bastante confuso, pero al menos es posible.
nickf
"evaluar" probablemente no sea la mejor palabra en ese comentario anterior. Umm ... asignar?
nickf
@eyelidlessness: Sí: fnName? fnName (): defaultFn (); // en una línea por sí solo, funciona
Ates Goral
4

Un poco más sobre el ejemplo de levik:

var foo = (condition) ? value1 : value2;
VirtuosiMedia
fuente
4
No necesitas el paréntesis. Los operadores ternarios también son comunes a muchos otros idiomas.
Ates Goral
1
Los paréntesis ayudan cuando hay ambigüedad sintáctica en el enunciado condicional (por ejemplo, determinar a qué componente del enunciado condicional se aplica el?).
párpados
4

La matriz # forEach en Javascript 1.6

myArray.forEach(function(element) { alert(element); });
Pablo Cabrera
fuente
4

Siguiendo obj || Sintaxis {predeterminada: verdadera}:

llamando a su función con esto: hola (needOne && requiredTwo && needThree) si un parámetro no está definido o es falso, llamará hola (falso), a veces útil

vvo
fuente
4

En situaciones de análisis con un conjunto fijo de componentes:

var str = "John Doe";

Puede asignar los resultados directamente a las variables, utilizando la "asignación de desestructuración" synatx:

var [fname, lname] = str.split(" ");
alert(lname + ", " + fname);

Que es un poco más legible que:

var a = str.split(" ");
alert(a[1] + ", " + a[0]);

Alternativamente:

var [str, fname, lname] = str.match(/(.*) (.*)/);

Tenga en cuenta que esta es una función de Javascript 1.7 . Así que esos son los navegadores Mozilla 2.0+ y Chrome 6+, en este momento.

Chris Noe
fuente
Intenté esto en la consola de Safari Javascript y resultó en un error de análisis.
párpados
Snap, supongo que solo lo he usado en Firefox. He añadido una nota de compatibilidad del navegador.
Chris Noe
No funciona en Chrome 6. Da SyntaxError: Unexpected token [.
RaYell
Un poco de investigación comienza a revelar que el 1.7 de Chrome no es del todo estándar. Según se informa, también hay un problema con let: stackoverflow.com/questions/300185/…
Chris Noe
Todavía no funciona en Chrome 13. ¿Alguna pista sobre cuándo se implementará?
pimvdb
3

Función de flecha inmediatamente invocada:

var test = "hello, world!";
(() => test)(); //returns "hello, world!";
Gerard Simpson
fuente
2

Olvidé:

(function() { ... }).someMethod(); // Functions as objects
párpados
fuente
2

Cree un literal de objeto anónimo con simplemente: ({})

Ejemplo: necesito saber si los objetos tienen el método valueOf:

var hasValueOf = !! ({}). valueOf

Azúcar sintáctico adicional: el doble no '!!' para convertir casi cualquier cosa en un booleano de manera muy sucinta.

mkoistinen
fuente
1

Me encanta poder evaluar () una cadena json y recuperar una estructura de datos completamente poblada. Odio tener que escribir todo al menos dos veces (una para IE, otra vez para Mozilla).

dicroce
fuente
1

Asignar las palabras clave de uso frecuente (o cualquier método) a variables simples como ths

  var $$ = document.getElementById;

  $$('samText');
RameshVel
fuente
3
Eso no funcionará (al menos en Chrome), porque thisse pierde el valor. En su lugar, debería usar document.getElementById.bind(document). Sin bindél es meramente asignar la HTMLDocument.prototype.getElementByIdfunción, sin la información que debe ser invocada document.
pimvdb
1

La clase Date de JavaScript proporciona una semi- "Interfaz fluida". Esto compensa el no poder extraer la parte de la fecha de una clase de fecha directamente:

var today = new Date((new Date()).setHours(0, 0, 0, 0));

No es una interfaz completamente fluida porque lo siguiente solo nos dará un valor numérico que en realidad no es un objeto de fecha:

var today = new Date().setHours(0, 0, 0, 0);
palswim
fuente
1

Respaldo predeterminado:

var foo = {}; // empty object literal

alert(foo.bar) // will alert "undefined"

alert(foo.bar || "bar"); // will alert the fallback ("bar")

Un ejemplo práctico:

// will result in a type error
if (foo.bar.length === 0)

// with a default fallback you are always sure that the length
// property will be available.
if ((foo.bar || "").length === 0) 
roosteronacid
fuente
1

Aquí hay uno que acabo de descubrir: verificación nula antes de llamar a la función:

a = b && b.length;

Este es un equivalente más corto a:

a = b ? b.length : null;

La mejor parte es que puede verificar una cadena de propiedades:

a = b && b.c && b.c.length;
lightblade
fuente
1

Me encanta lo sencillo que es trabajar con listas:

var numberName = ["zero", "one", "two", "three", "four"][number];

Y hashes:

var numberValue = {"zero":0, "one":1, "two":2, "three":3, "four":4}[numberName];

En la mayoría de los otros lenguajes, este código sería bastante pesado. Los valores predeterminados también son encantadores. Por ejemplo, informe de códigos de error:

var errorDesc = {301: "Moved Permanently",
                 404: "Resource not found",
                 503: "Server down"
                }[errorNo] || "An unknown error has occurred";
manixrock
fuente
Eso se ve increíble, ¿cuál es el nombre técnico de esto?
TrySpace
0

int to string cast

var i = 12;
var s = i+"";
Martijn Laarman
fuente
3
Esto no me parece más "dulce" que hacer un i.toString () o String (i) directo. ¡Corto! = Azúcar.
Ates Goral
0
element.innerHTML = "";  // Replaces body of HTML element with an empty string.

Un atajo para eliminar todos los nodos secundarios del elemento.

pramodc84
fuente
6
Eso no es realmente Javascript, es DOM, y actualmente no es estándar en eso.
párpados
0

Convierta la cadena a un entero por defecto a 0 si es imposible,

0 | "3" //result = 3
0 | "some string" -> //result = 0
0 | "0" -> 0 //result = 0

Puede ser útil en algunos casos, principalmente cuando 0 se considera un mal resultado

Raimonds
fuente
0

Literales de plantilla

var a = 10;
var b = 20;
var text = `${a} + ${b} = ${a+b}`;

¡entonces la variable de texto será como la siguiente!

10 + 20 = 30

Mohan Kumar
fuente