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?


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");

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

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}>;

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; };
})()

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;
}

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

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í .


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.

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.


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;
}

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.


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"

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

¿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;

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

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


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.


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!";

2

Olvidé:

(function() { ... }).someMethod(); // Functions as objects

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.


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).


1

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

  var $$ = document.getElementById;

  $$('samText');

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);

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) 

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;

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";

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+"";

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.


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


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.