¿Cuáles son algunas técnicas avanzadas de JavaScript que no ve con frecuencia pero que debería ver?

Observables Son como Promesas, pero más poderosas. El uso del patrón observable (también llamado programación funcional reactiva [1]) realmente puede limpiar su código asincrónico de JavaScript. Las bibliotecas más populares parecen ser RxJS y Bacon.JS, pero hay muchas por ahí. Me gusta RxJS.

Básicamente, los Observables le permiten usar una buena programación funcional antigua (por ejemplo, mapear, reducir, filtrar, escanear) en flujos de datos asíncronos (por ejemplo, solicitudes AJAX, eventos de clic). Luego puede suscribir funciones a estos flujos que representarán su IU, actualizarán sus modelos, generarán más flujos, etc. Esto permite un estilo de programación más declarativo .

Para un poco de diversión , mira este video de YouTube de esta persona líder de Netflix Cross Team Tech sobre cómo hacen el desarrollo frontend asíncrono

Y para un buen tutorial para principiantes, echa un vistazo a esta esencia de André Staltz.

[1] Se debate si el título FRP realmente se aplica a lo que están haciendo las bibliotecas como RxJS.

Cree un objeto basado en un prototipo real en lugar de intentar crear un objeto psuedo-clásico “similar a Java”.

Probablemente el mayor error del diseño de JavaScript fue la inclusión de la nueva palabra clave. No use new , use Object.create () en su lugar. En otras palabras, no hagas esto:

función MyClass () {};

MyClass.prototype.method1 = function () {…};
MyClass.prototype.method2 = function () {…};
// …
MyClass.prototype.methodN = function () {…};

instancia var = new MyClass ();

En su lugar, cree un objeto prototipo y evite cualquier referencia tonta a MyClass.prototype. *:

var myProto, makeInstance, instancia;

myProto = {
método1: función () {…},
método2: función () {…},
// …
methodN: function () {…}
};

makeInstance = function () {return Object.create (myProto); };

instancia = makeInstance ();

Ahora me doy cuenta de que esto no parece proporcionar una ventaja significativa en este ejemplo trivial. Sin embargo, en proyectos más grandes esto da como resultado un código mucho más legible porque la palabra ‘prototipo’ no es el 33% de su código. Eche un vistazo a algunas “clases” de la Biblioteca de cierre de Google si desea tener una idea de lo horrible que puede ser.

La función makeInstance no solo puede crear una instancia, sino también hacer otras cosas interesantes y maravillosas, como realizar un seguimiento de todas las instancias en la memoria y establecer propiedades iniciales basadas en el estado actual de la aplicación . También se puede usar una función de cierre (en lugar de un objeto literal) para crear métodos verdaderamente privados para el prototipo. Y, quizás lo más importante, la gente no confundirá esto con un sistema de objetos basado en la clase. Lo cual es bueno, porque el objeto de JavaScript no está basado en clases.

Echa un vistazo a TypeBomb. Cada elemento en la pantalla tiene un objeto de fábrica basado en prototipos correspondiente con las rutinas makeInstance y destroyInstance . Debido a este enfoque, el modelo puede responder fácilmente preguntas sobre grupos de objetos (¿Cuántas palabras en la pantalla? ¿Cuántas están cerca de la parte inferior?). Este es un código que aprovecha los objetos basados ​​en prototipos de JavaScript en lugar de usar errores engañosos y detallados para que parezcan objetos Java.

Esta no es realmente una técnica avanzada, sino un pequeño truco que puedes usar en JavaScript. Como probablemente ya sabe, JavaScript utiliza internamente registros de punto flotante para almacenar números. Entonces, si necesita una forma rápida de asegurarse de que un número pequeño sea un número entero , puede redondearlo hacia abajo con el operador de complemento de doble bit , como tal:

v = ~~v;

Siempre devolverá un número entero (nunca un NaN ) y establecerá v en 0 si no fuera un número.

PD. Algo a tener en cuenta con este enfoque es que el número se encuentre dentro de los límites de un entero de 32 bits con signo (o de -2147483648 a 2147483647, inclusive). De lo contrario, use su Math.floor () habitual. Esta limitación se debe al hecho de que técnicamente estamos haciendo una operación bit a bit en el número (eso es lo que implícitamente lo convierte en un número entero) y, por lo tanto, tenemos que “encajar” dentro del bitness interno del motor de JavaScript.

Una técnica que descubrí recientemente es lo que llamo “mensajes verificados en tiempo de ejecución”. Entonces, en lugar de llamar a un método en otro objeto directamente, o enviar eventos / comandos basados ​​en cadenas que no tienen una estructura definida, envía mensajes que verifican su estructura / carga / parámetros.

Hay múltiples beneficios:

  1. Desacopla el emisor / receptor (nada nuevo -> eventos / bus de eventos, etc.)
  2. Contrato bien definido entre remitente / receptor (los mensajes son el contrato)
  3. Pruebas unitarias que prueban lo real (corrección de mensajes) pero no requieren la parte receptora o de envío durante la prueba.
  4. Los mensajes son instancias de clase, no solo literales de objetos anónimos
  5. Los mensajes pueden verificar cualquier cosa, desde cadenas simples, números hasta ValueObjects comerciales. Esto simplifica su código, ya que no tiene que repartir las comprobaciones alrededor de su base de código (DRY)

Básicamente, esto es lo que obtienes con los compiladores de verificación de tipos estáticos en otros idiomas y solucionó uno de los mayores dolores de cabeza que experimenté en las grandes aplicaciones de Javascript: ¡refactorización!

Esta no es una técnica avanzada, pero rara vez se ve. El acceso a propiedades profundas se puede comprimir mediante el uso de variables con referencias o cadenas.

Las clases a menudo se escriben de una manera muy detallada:

!function () {
// ...
function MyClass() {}
MyClass.prototype.method1 = function () {};
MyClass.prototype.method2 = function () {};
// ...
MyClass.prototype.methodN = function () {};
// ...
}();

Más conciso y mejor para la minificación:

!function () {
// ...
// Note that the MyClass function definition is automatically hoisted.
var _proto = MyClass.prototype;
function MyClass() {}
_proto.method1 = function () {};
_proto.method2 = function () {};
// ...
_proto.methodN = function () {};
// Some deprecated method could be aliased, too:
_proto.methodX = _proto.methodDeprecated;
// ...
}();

Aún más conciso si tiene una función ‘extender’ en sus manos, aunque la siguiente sintaxis requiere hacer un seguimiento de la coma final y limita la libertad de alias de múltiples nombres en el mismo método:

var extend = require('util')._extend;
function MyClass() {}
extend(MyClass.prototype, {
method1: function () {},
method2: function () {},
// ...
methodN: function () {}
});

Otro acortamiento para la minificación viene para los nombres largos de funciones que se usan con frecuencia. Ver fuente jQuery para mejores ejemplos. El siguiente ejemplo es sintético solo para demostrar el principio:

!function (global) {
//< minifies to `!function(a){`

var someObject = global.someObject;
//

var someLongMethodOrFunctionName_str = 'someLongMethodOrFunctionName';
//

someObject [someLongMethodOrFunctionName_str] ();
//

// Debajo de muchas llamadas a `someLongMethodOrFunctionName`
// debería seguir, de lo contrario la optimización es inútil.
}(esta);

Muchas de las técnicas mencionadas en otras respuestas se colocan mejor en la pared 🙂

Solo me gustaría mencionar esa cosa funky que muchos han creído imposible. También contradice la respuesta de Mike Mikowski a ¿Cuáles son algunas técnicas avanzadas de JavaScript que no ve con frecuencia pero que debería ver? ya que demuestra cuán importantes son la new palabra clave y los constructores de funciones.

Tan bien. Estaba pensando si sería posible que varias funciones tuvieran acceso a la “misma” propiedad privada que, por supuesto, está en un cierre. Normalmente, puede devolver una función para acceder a la propiedad privada como esta

var f1, f2;
función f (n) {
var secreto = n;
función de retorno () {
console.log (secreto);
}
}
f1 = f (2);
f2 = f (4);
f1 (); // 2
f2 (); // 4

Entonces esto es normal. f1 y f2 tienen sus propios cierres creados en diferentes instancias y no pueden compartir la misma propiedad privada. ¿Se puede compartir una propiedad privada? Gracias a los constructores y la estructura prototípica de JS; ¡la respuesta es sí!

Ok, mira esto.

var SharePrivate = (function () {
var private = “Secreto”;
función SharePrivate () {}
SharePrivate.prototype.getPrivate = function () {
volver privado;
}
SharePrivate.prototype.setPrivate = function (value) {
privado = valor;
}
devolver SharePrivate;
}) ();

var a = new SharePrivate ();
console.log (a.getPrivate ()); // “Secreto”
var b = nuevo SharePrivate ();
console.log (b.getPrivate ()); // “Secreto”
a.setPrivate (“Derrame”);
console.log (a.getPrivate ()); // “Derrame”
console.log (b.getPrivate ()); // “Derrame” wow .. !!
console.log (a.hasOwnProperty (“getPrivate”)); // falso.
console.log (a.private); // indefinido
console.log (SharedPrivate.private); // indefinido -> sigue siendo privado

Por cierto, este no es mi invento y el crédito va a https://stackoverflow.com/questi

Bien, esta es mi invención, que en realidad está haciendo lo mismo, pero el código es mucho más fácil de entender.

function SharedPrivate () {
var private = “secret”;
this.constructor.prototype.getP = function () {return private}
this.constructor.prototype.setP = function (v) {private = v;}
}
var o1 = new SharedPrivate ();
var o2 = new SharedPrivate ();
console.log (o1.getP ()); // secreto
console.log (o2.getP ()); // secreto
o1.setP (“Pentax Full Frame K1 está a la venta …!”);
console.log (o1.getP ()); // ¡Pentax Full Frame K1 está a la venta ..!
console.log (o2.getP ()); // ¡Pentax Full Frame K1 está a la venta ..!
o2.setP (“Y es solo por $ 1,795._”);
console.log (o1.getP ()); // Y es solo por $ 1,795._
console.log (SharedPrivate.private); // indefinido -> sigue siendo privado

No quiero explicar cada punto clave, ya que puedes encontrar una mejor explicación en google. Entonces aquí va:
1. alcance de la función, cierre y cierre globales verificables
el alcance de los cierres es muy confuso y debe ser muy claro al respecto, ya que ayuda a que el código sea un poco complicado y se puede administrar para evitar pérdidas de memoria

2. Herencia prototípica:
Es muy complicado y diferente de la herencia clásica. debe saber esto para usar el comportamiento de OOP de javascript.

3. AJAX:
Sé que todos lo saben pero, al mismo tiempo, es una de las características más importantes de JavaScript. Debe saber esto para crear un sitio web receptivo y de una página.

4. Memorización:
bueno. Puede que este no sea el punto clave según muchos, pero el almacenamiento en caché de datos es una de las cosas que debe aprender para que su sitio web funcione también con una conexión lenta a Internet.

5. Marco:
Los marcos ahora son días en todas partes. Tienes que encontrar mucho tiempo ahorrado, cuando cambias a un sitio web basado en framework desde un sitio web escrito en JavaScript simple.

El uso de operadores ternarios es algo que no veo en la mayoría de las bibliotecas y, por lo tanto, diría que esto es algo que uno debería usar con más frecuencia. En lugar de usar declaraciones if-else de una sola línea o una cadena de declaraciones de una sola línea, puede usar operadores ternarios encadenados. ¡La mejor parte con ellos es que puedes llamar ‘nulo’ en caso de que no haya otra parte!
Esto es algo que hago regularmente:

condición_met? call_function (): nulo;

Lo uso incluso en declaraciones de eco:

console.log (my_condition? ‘Hi!’: (your_condition? ‘Hello’: ‘Ñamaste’));

Otra cosa que la gente suele ignorar es el uso de “uso estricto”. Esta es una nueva directiva disponible en JavaScript 1.8.5 y posterior. Esto ejecuta la secuencia de comandos en un modo estricto y le permite detectar cualquier error suelto. Por flojo me refiero al uso de cualquier cosa no declarada previamente, que podría ser variables no declaradas, objetos, funciones, etc. Esto es especialmente útil cuando está desarrollando el código y asegura que cuando entregue el código, no habrá cualquier error Si bien puede seguir esto, no se sugiere.

Puede usar bind() para curry, que ha existido por un tiempo pero no lo ve usado mucho. Está limpio y no se necesitan bibliotecas 🙂

Fuente: Alguna conversación que tuve con getify alguna vez, Curry en JavaScript usando bind ()

Mi mejor consejo para escribir JavaScript “avanzado” es el siguiente:
Mi opinión sobre el tema puede no ser exactamente lo que esperas. Siempre estoy tratando de promover mejores prácticas de modelado y un código menos desordenado. La clave para lograr esto, en mi opinión, es a través de JavaScript desacoplado adecuadamente donde mantiene su vista (html) separada de sus objetos JavaScript. Esto no solo hará que su código sea reutilizable, sino que también sea muy verificable.

Utilizando más del paradigma funcional, aprovechando .map y .reduce, e introduciendo estructuras de datos inmutables en su programa: facebook / immutable-js.

Para convertir a booleano puedes usar:
!!(expression) .

Cualquier expresión que sea verdadera se vuelve verdadera. Cualquier expresión de expresión que sea falsa (cadena vacía, 0, nula, indefinida, etc.) se convierte en falsa.

Otra técnica implica regresar temprano para condiciones de error.

Por ejemplo, si tiene un código similar al siguiente:

if (condición) {
// manejar el caso de éxito
} más {
// manejar el error
}

Puedes convertirlo a:

si (! condición) vuelve;
// manejar el caso de éxito

El beneficio es que el código es mucho más limpio, más corto y hay menos sangría. También separa los errores de la lógica normal. Esto es especialmente beneficioso cuando hay múltiples condiciones anidadas.

Estos se usan con frecuencia, pero son buenos trucos que puedes usar.

Transmita un entero con signo a un entero sin signo:
num >>> 0

Establecer todos los bits (útil para crear máscaras):
~0

No estoy seguro de si considerarías esto avanzado, pero es una técnica que probablemente he estado abusando desde que me enteré …

Usando ternaries para llamar funciones o variables condicionalmente.
Por ejemplo, si puede estar usando Velocity.js y así, en lugar de usar “jQuery.animate ()”, usará “jQuery.velocity ()”.

Ahora es posible que desee hacer esto condicionalmente, tal vez usando animar para ciertos dispositivos, así que en lugar de usar una instrucción if / else cada vez que pueda escribir:

jQuery[(theCondition) ? 'velocity' : 'animate']({settings...});

o mejor aún, mover el ternario a un ámbito de aplicación para ser reutilizado …

var animationMethod = (theCondition) ? 'velocity' : 'animate';

y solo llama así:

jQuery[animationMethod]({settings...});

¡La idea de usar una variable para contener la referencia clave de un objeto como una cadena es algo que generalmente encuentro bastante útil!

Compartir mucho código entre el cliente y el servidor, también conocido como “Javascript isomórfico”. (¡gracias, Sarah Federman!) Es una cosa extremadamente poderosa que está permitida por node.js, pero la mayoría de las personas rara vez la usa, o solo se usa para las cosas más triviales.

He estado trabajando en emular métodos de extensión en JavaScript últimamente. Le permite agregar nueva funcionalidad a los objetos existentes sin “parchearlos”:

Métodos de extensión en JavaScript por Mike Austin en Structura

Lo usas así:

var _capitalize = extend (String, _capitalize, function () {
devuelve this [0] .toUpperCase () + this.slice (1);
});
var foo = _capitalize.apply (“foo”);

La sintaxis de apply () se puede acortar a una llamada de función con un poco de trabajo extra:

_capitalize (“foo”);

Es parte de un proyecto más grande para crear un lenguaje que compila a JavaScript.

Las promesas no son avanzadas, no son muy difíciles de aprender y son extremadamente útiles; y de alguna manera la gente les tiene miedo y no los está usando.

Yo diría que si no estás usando promesas, ¡deberías hacerlo ahora!

Usar `Array.reduce` y los métodos de encadenamiento es algo que no veo con tanta frecuencia y en realidad es bastante bueno.

Pero por favor no confíes tanto en lodash. Prueba polyfills en su lugar

“uso estricto”;

const someArrayOfObjects = [
{id: “one”, valor: “oneValue”},
{id: “dos”, valor: “dosValor”},
{id: “tres”, valor: “tresValor”}
]

const objectOnly = someArrayOfObjects.filter (item => item.id! == “two”) // Solo por diversión
.reduce (función (resultado, elemento) {
resultado [item.id] = item.value
resultado de retorno;
}, {});

console.log (objectOnly); // {one: ‘oneValue’, three: ‘threeValue’}

const backToArray = Object.keys (objectOnly)
.filter (key => key! == “three”) // Solo por diversión
.map (key => ({id: key, value: objectOnly [key]}));

console.log (backToArray); // [{id: ‘one’, valor: ‘oneValue’}]

Con una combinación de promesas, puede hacer un código increíblemente legible.

Ahora que async / await son parte de la especificación del lenguaje central, debería usarlos en lugar de cadenas de promesa. En general, son más fáciles de entender y más legibles en código.

Seguramente debería usar los operadores de descanso y dispersión, y la funcionalidad de desestructuración en general.

Los generadores son la forma en que se deben proporcionar los iterables. Son extremadamente potentes, especialmente cuando se combinan con la funcionalidad asincrónica descrita anteriormente.

La palabra clave de class en JavaScript puede ser simplemente azúcar sintáctica, pero mejora la organización del código y oculta una gran complejidad de lenguaje. El uso de captadores y establecedores en las clases ayuda a ocultar la información (a pesar de que no hay un control de acceso real, los transpiladores como TypeScript pueden verificar si hay propiedades ilegales y acceso a funciones de miembros).

Probablemente sea más consejo para los desarrolladores que vienen a JS desde otro idioma, pero el uso de operadores de comparación de verificación de tipo debería ser algo que se use prácticamente todo el tiempo, específicamente === or !== lugar de == or !=

More Interesting

¿Cómo sobreviven los desarrolladores front-end de los creadores de sitios web gratuitos, como Weebly y Wix, que se han vuelto cada vez más sofisticados y personalizables?

¿Cómo puedo desarrollar un sitio web que sea igual a Ola Cab?

¿Cuál es la mejor manera de hacer el análisis de mercado sobre mi idea de complemento de WordPress antes de saltar al desarrollo?

¿Es justo decir que JavaScript y PHP siguen siendo "inferiores" a otros lenguajes de programación, a pesar de sus encarnaciones modernas como PHP7 y ES2015 +?

Suponiendo que no trabajemos para una startup de alto tráfico, ¿cuál es una cantidad aceptable de conocimiento de back-end que un desarrollador web de pila completa debería saber?

¿Cuáles son las implicaciones del archivo de búsqueda cada vez menor de Twitter?

Cómo reducir el TTFB (Tiempo hasta el primer byte) para una página web

¿Debo aprender Java y desarrollo web lado a lado?

Cómo crear un archivo robots.txt para mi sitio web

¿Por qué Quora eligió Python para su desarrollo? ¿Qué desafíos tecnológicos enfrentaron los fundadores antes de decidirse por Python en lugar de PHP?

Cómo trabajar de forma independiente como diseñador web

¿Qué marco Javascript debería aprender?

¿Los filtros Laravel también funcionan en múltiples acciones de controlador?

Cómo aprender diseño de sitios web

¿Cómo configuraría su computadora / navegador para que cada vez que visite http://events.dev.com/ se muestre el contenido de http: //localhost/events/index.htm?