Uso adecuado de const para definir funciones
¿Existe algún límite en cuanto a los tipos de valores que se pueden establecer const
en JavaScript y, en particular, las funciones? ¿Es esto válido? Es cierto que funciona, pero ¿se considera una mala práctica por algún motivo?
const doSomething = () => {
...
}
¿Deberían definirse todas las funciones de esta manera en ES6? No parece que esto haya tenido éxito, si es así.
No hay ningún problema con lo que has hecho, pero debes recordar la diferencia entre declaraciones de funciones y expresiones de funciones.
Una declaración de función, es decir:
function doSomething () {}
Se eleva completamente a la parte superior del alcance (y let
también const
tienen alcance de bloque).
Esto significa que lo siguiente funcionará:
doSomething() // works!
function doSomething() {}
Una expresión de función, es decir:
[const | let | var] = function () {} (or () =>
Es la creación de una función anónima ( function () {}
) y la creación de una variable, y luego la asignación de esa función anónima a esa variable.
Entonces, las reglas habituales sobre el levantamiento de variables dentro de un alcance: las variables con alcance de bloque ( let
y const
) no se elevan hasta undefined
la parte superior de su alcance de bloque.
Esto significa:
if (true) {
doSomething() // will fail
const doSomething = function () {}
}
Fallará ya que doSomething
no está definido. (Arrojará un ReferenceError
)
Si cambia a usar, var
obtendrá la elevación de la variable, pero se inicializará para undefined
que el bloque de código anterior aún no funcione. (Esto generará un mensaje TypeError
ya que doSomething
no es una función en el momento en que lo llames)
En lo que respecta a las prácticas estándar, siempre debes utilizar la herramienta adecuada para el trabajo.
Axel Rauschmayer tiene una excelente publicación sobre alcance y elevación, incluida la semántica de es6: Variables y alcance en ES6
Aunque usar const
para definir funciones parece un truco, tiene grandes ventajas que lo hacen superior (en mi opinión).
Hace que la función sea inmutable, por lo que no tiene que preocuparse de que algún otro fragmento de código cambie esa función.
Puede utilizar la sintaxis de flecha gruesa, que es más corta y limpia.
El uso de funciones de flecha se encarga del
this
enlace por usted.
ejemplo confunction
// define a function
function add(x, y) { return x + y; }
// use it
console.log(add(1, 2)); // 3
// oops, someone mutated your function
add = function (x, y) { return x - y; };
// now this is not what you expected
console.log(add(1, 2)); // -1
mismo ejemplo conconst
// define a function (wow! that is 8 chars shorter)
const add = (x, y) => x + y;
// use it
console.log(add(1, 2)); // 3
// someone tries to mutate the function
add = (x, y) => x - y; // Uncaught TypeError: Assignment to constant variable.
// the intruder fails and your function remains unchanged
Han pasado tres años desde que se hizo esta pregunta, pero recién ahora me estoy encontrando con ella. Dado que esta respuesta está tan abajo en la pila, permítame repetirla:
P: Me interesa saber si existen límites sobre los tipos de valores que se pueden establecer usando const en JavaScript, en particular funciones. ¿Es esto válido? Es cierto que funciona, pero ¿se considera una mala práctica por algún motivo?
Me motivé a investigar un poco después de observar a un prolífico codificador de JavaScript que siempre usa const
declaraciones para functions
, incluso cuando no hay ninguna razón/beneficio aparente.
En respuesta a "¿ se considera una mala práctica por algún motivo? ", permítame decir, en mi opinión, sí lo es, o al menos, el uso de declaraciones tiene ventajasfunction
.
Me parece que esto es en gran medida una cuestión de preferencia y estilo. Hay algunos buenos argumentos presentados anteriormente, pero ninguno tan claro como se hace en este artículo:
Confusión constante: por qué sigo usando declaraciones de funciones de JavaScript por medium.freecodecamp.org/Bill Sourour, gurú, consultor y profesor de JavaScript.
Insto a todos a leer ese artículo, incluso si ya han tomado una decisión.
Estos son los puntos principales:
Las declaraciones de función tienen dos ventajas claras sobre las expresiones de función [const]:
Ventaja n.º 1: claridad de intenciones
Al escanear miles de líneas de código al día, es útil poder descubrir la intención del programador de la forma más rápida y sencilla posible.
Ventaja #2: Orden de declaración == orden de ejecución
Idealmente, quiero declarar mi código más o menos en el orden en que espero que se ejecute.
Esto es lo mejor para mí: cualquier valor declarado usando la palabra clave const es inaccesible hasta que la ejecución lo alcance.
Lo que acabo de describir arriba nos obliga a escribir código que parece al revés. Tenemos que comenzar con la función de nivel más bajo y avanzar hacia arriba.
Mi cerebro no funciona de esa manera. Quiero el contexto antes que los detalles.
La mayor parte del código está escrito por humanos. Por lo tanto, tiene sentido que el orden de comprensión de la mayoría de las personas siga aproximadamente el orden de ejecución de la mayor parte del código.
Hay casos especiales en los que arrow functions
simplemente no funcionan:
Si estamos cambiando un método de una API externa y necesitamos la referencia del objeto.
Si necesitamos usar palabras clave especiales que sean exclusivas de la
function
expresión:arguments
,yield
,bind
etc. Para más información: Limitaciones de la expresión de la función de flecha
Ejemplo:
Asigné esta función como controlador de eventos en la Highcharts
API. Lo activa la biblioteca, por lo que la this
palabra clave debe coincidir con un objeto específico.
export const handleCrosshairHover = function (proceed, e) {
const axis = this; // axis object
proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); // method arguments
};
Con una función de flecha, this
coincidiría con el alcance de la declaración y no tendremos acceso al objeto API:
export const handleCrosshairHover = (proceed, e) => {
const axis = this; // this = undefined
proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); // compilation error
};