Cómo escribir código JS de alta calidad_Conocimientos básicos
Quiero escribir una biblioteca de clases de JavaScript eficiente pero no sé cómo empezar;
Intento leer las bibliotecas de clases de otras personas, pero parece que las entiendo <; /p>
Planeo hacerlo bien Estudiando las funciones avanzadas de JS, pero el contenido del libro autorizado está demasiado fragmentado
Incluso si recuerdo el "uso", no lo recuerdo. piense en el "método" cuando se trata de "usarlo".
Quizás eres como yo, parece haber una fuerza invisible que limita nuestros planes, haciéndonos pensar repetidamente en las limitaciones del conocimiento, provocando que nos quedemos quietos y nos cueste avanzar.
Durante este período, la presión se duplicó debido a diversas asignaciones, diseño del curso e informes experimentales. Es raro sacar un poco de tiempo, no dormir hasta tarde, organizar y resumir los libros que leí en el pasado, solo para estar más cerca de escribir mi propia biblioteca de clase.
Este artículo hace referencia a la "Esencia del lenguaje Javascript" y al "JavaScript efectivo". Los ejemplos han sido depurados y, después de comprenderlos, quiero simplificar un poco algunos principios "profundos".
1. Alcance variable
El alcance es como oxígeno para los programadores. Está en todas partes y muchas veces ni siquiera piensas en ello. Pero cuando está contaminado (por ejemplo, al usar objetos globales), puede sentirse asfixiado (por ejemplo, la aplicación se vuelve menos receptiva). Las reglas básicas de alcance de JavaScript son simples, bien diseñadas y poderosas. El uso eficaz de JavaScript requiere dominar algunos conceptos básicos de alcance variable y comprender algunos casos extremos que pueden generar problemas difíciles de alcanzar y desagradables.
1.1 Utilice variables globales lo menos posible
Javascript puede crear fácilmente variables en el espacio de nombres global. Crear una variable global es sencillo porque no requiere ningún tipo de declaración y todo el código del programa accede automáticamente a ella.
Para principiantes como nosotros, cuando encontramos ciertas necesidades (por ejemplo, los datos transmitidos se registran, esperando una determinada oportunidad para usarse cuando se llama a una determinada función; o una determinada función se utiliza con frecuencia) , No podemos dudar en pensar en ello. Las funciones globales, e incluso el pensamiento orientado a procesos del lenguaje C aprendido en el primer año, están demasiado arraigados y el sistema está perfectamente lleno de funciones. La definición de variables globales contamina el espacio de nombres público compartido y puede provocar conflictos de nombres inesperados. Las variables globales también son perjudiciales para la modularidad porque conducen a un acoplamiento innecesario entre componentes independientes de un programa. Hablando en serio, demasiados globales (incluidas hojas de estilo, que definen directamente el estilo de div o a) se convertirán en un error catastrófico cuando se integren en un proceso de desarrollo de varias personas. Es por eso que todo el código de jQuery está envuelto en una expresión anónima que se ejecuta inmediatamente: una función anónima que se autollama. Cuando el navegador carga el archivo jQuery, la función anónima autollamada comienza inmediatamente a ejecutarse e inicializa cada módulo de jQuery para evitar dañar y contaminar las variables globales y afectar otros códigos.
El código es el siguiente:
(función(ventana, undefinida){
var jQuery = ...
// ...
window.jQuery = window.$ = jQuery;
})(window
Además, puedes pensar, "escribe lo que sea". lo que desea primero, es más fácil "organizarlo más tarde", pero los buenos programadores prestarán atención constantemente a la estructura del programa, continuarán agrupando funciones relacionadas y separarán componentes irrelevantes como parte del proceso de programación.
Dado que el espacio de nombres global es la única forma en que interactúan los componentes independientes en un programa JavaScript, el uso de controles con nombres globales es inevitable. Los componentes o bibliotecas tienen que definir algunas variables globales. para uso de otras partes del programa. De lo contrario, es mejor utilizar variables locales.
El código es el siguiente:
this.foo; //undefinido
foo = "global foo";
this. foo;/ /"global foo"
var foo = "global foo";
this.foo = "cambiado";
foo; //cambiado
El espacio de nombres global de JavaScript también se expone como un objeto global accesible en el alcance global del programa, que sirve como valor inicial de esta palabra clave. En los navegadores web, los objetos globales están vinculados a la variable de ventana global. Esto significa que tiene dos formas de crear una variable global: declararla usando var en el alcance global o agregarla al objeto global. La ventaja de utilizar la declaración var es que puede expresar claramente el impacto de las variables globales en el alcance del programa.
Dado que las referencias a variables globales vinculadas pueden causar errores de tiempo de ejecución, mantener los alcances claros y concisos hará que sea más fácil para los usuarios de su código comprender qué variables globales declara el programa.
Dado que el objeto global proporciona un mecanismo de respuesta dinámica para el entorno global, puede usarlo para consultar un entorno en ejecución y detectar qué funciones están disponibles en esta plataforma.
Por ejemplo, ES5 introduce un objeto JSON global para leer y escribir datos en formato JSON.
El código es el siguiente:
if(!this.JSON){
this.JSON = {
parse: . .,
stringify: ...
}
}
Si proporciona una implementación JSON, por supuesto puede usar su propia realización simple e incondicional. Pero las implementaciones integradas proporcionadas por el entorno de alojamiento son casi más adecuadas porque están escritas en C en el navegador. Porque se verifican rigurosamente su corrección y coherencia con respecto a ciertos estándares y, en general, brindan un mejor rendimiento que las implementaciones de terceros.
El curso de estructura de datos original fue diseñado para simular las operaciones básicas de cadenas, requiriendo que no se puedan utilizar los métodos proporcionados por el propio lenguaje. JavaScript implementa muy bien las operaciones básicas en matrices. Si es solo para necesidades generales de aprendizaje, la idea de simular los métodos proporcionados por el lenguaje en sí es buena, pero si realmente inviertes en desarrollo, no es necesario. considere usar los métodos integrados de JavaScript en primer lugar.
1.2 Evite el uso de with
La declaración with proporciona "conveniencia" y hace que su aplicación sea poco confiable e ineficiente. Necesitamos llamar una serie de métodos en un solo objeto en secuencia. El uso de la instrucción with puede evitar fácilmente referencias repetidas a objetos:
El código es el siguiente:
estado de función(info){
var widget = new Widget (
con(widget){
setBackground("azul"
setForeground("blanco"); setText ("Estado: " info);
show();
}
}
Utilice la instrucción with del módulo. objeto" También es tentador importar variables.
El código es el siguiente:
función f(x, y){
with(Math){
return min( round(x), sqrt(y)); //Referencia abstracta
}
}
De hecho, JavaScript trata todas las variables por igual. JavaScript busca variables comenzando desde el ámbito más interno y trabajando hacia afuera. El lenguaje with trata un objeto como si representara el alcance de una variable, por lo que dentro de un bloque with, la búsqueda de variables comienza buscando las propiedades del nombre de variable dado. Si la propiedad no se encuentra en este objeto, la búsqueda continúa en el ámbito externo. Cada referencia a una variable externa en un bloque with supone implícitamente que no hay ninguna propiedad con el mismo nombre en el objeto with (ni en ninguno de sus objetos prototipo). Crear o modificar el objeto with o su objeto prototipo en otra parte del programa no necesariamente sigue esta suposición. Por supuesto, el motor JavaScript no leerá el código local para saber qué variables locales utiliza. Los ámbitos de JavaScript se pueden representar como estructuras de datos internas eficientes y las búsquedas de variables pueden ser muy rápidas. Sin embargo, debido a que el bloque de código with necesita buscar en la cadena prototipo del objeto para encontrar todas las variables en el código with, su velocidad de ejecución es mucho más lenta que la de los bloques de código ordinarios.
En lugar del lenguaje with, un enfoque simple es vincular el objeto a un nombre corto de variable.
El código es el siguiente:
estado de función(info){
var w = new Widget();
w. setBackground(" azul");
w.setForeground("blanco");
w.setText("Estado: " información);
w. show() ;
}
En otros casos, el mejor enfoque es vincular explícitamente la variable local a la propiedad relevante.
El código es el siguiente:
función f(x, y){
var min = Math.min,
ronda = Matemáticas. ronda,
sqrt = Math.sqrt;
return min(round(x), sqrt(y)); >
1.3 Competente en cierres
Comprender los cierres tiene un solo concepto:
a) JavaScript le permite hacer referencia a variables definidas fuera de la función actual.
El código es el siguiente:
function makeSandwich(){
var magicIngredient = "mantequilla de maní"
function make( relleno){
return ingrediente mágico " y " relleno
}
return make("gelatina"); p>
makeSandwich(); // "mantequilla de maní y mermelada"
b) Incluso si la función externa ha regresado, la función actual aún puede hacer referencia a las variables definidas en la función externa
El código es el siguiente:
función makeSandwich(){
var magicIngredient = "mantequilla de maní"
function make(relleno){
return magicIngredient " y " relleno
}
return make
}
var f =; sandwichMaker();
f("gelatina"); // "mantequilla de maní y mermelada"
f("plátanos"); // "mantequilla de maní y plátanos" p>
f("mallows "); // "mantequilla de maní y malvas"
Los valores de las funciones de javascriptd contienen más información que el código requerido para ejecutar cuando se llaman. Además, los valores de las funciones de JavaScript también almacenan internamente variables a las que pueden hacer referencia y que están definidas en su alcance adjunto. Las funciones que realizan un seguimiento de las variables dentro del alcance que cubren se denominan cierres.
La función make es un cierre y su código hace referencia a dos variables externas: magicIngredient y filling. Siempre que se llama a la función make, su código puede hacer referencia a estas dos variables porque el cierre almacena estas dos variables.
Una función puede hacer referencia a cualquier variable dentro de su alcance, incluidos parámetros y variables de función externa. Podemos aprovechar esto para escribir una función SandwichMaker más general.
El código es el siguiente:
function makeSandwich(magicIngredient){
function make(filling){
return magicIngredient " y " relleno;
}
return make;
}
var f = sandwichMaker("jamón"); p>
f("queso"); // "jamón y queso"
f("mostaza"); // "jamón y mostaza"
El cierre es el JavaScript más elegante y elegante Una de las propiedades expresivas y el núcleo de muchos modismos.
c) Los cierres pueden actualizar el valor de variables externas. De hecho, los cierres almacenan referencias a variables externas, no copias de sus valores.
Por lo tanto, se pueden realizar actualizaciones para cualquier cierre que tenga acceso a estas variables externas.
El código es el siguiente:
function box(){
var val = indefinido;
return {
establecer: función(newval) {val = newval;},
obtener: function (){return val;},
tipo: function(){return typeof val ;}
};
}
var b = caja();
b.type(); /p>
b.set(98.6);
b.get(); //98.6
b.type(); //número
El ejemplo produce un objeto que contiene tres cierres. Estos tres cierres son propiedades de establecimiento, tipo y obtención. Todos comparten acceso a la variable val. El cierre establecido actualiza el valor de val. Luego llame a get y escriba para ver los resultados actualizados.
1.4 Comprensión de la promoción de declaración de variables
Javascript admite este método de alcance (una referencia a la variable foo estará vinculada al alcance más cercano a la declaración de la variable foo), pero no bloques de soporte Alcance de nivel (el alcance de la definición de una variable no es el alcance de su declaración o bloque de código adjunto más cercano).
No comprender esta función provocará algunos errores sutiles:
El código es el siguiente:
la función esWinner(jugador, otros){
var más alto = 0;
for(var i = 0, n = otros.longitud; i más alto){
más alto = jugador.puntuación; p> }
}
return player.score gt;
}
1.5 Tenga cuidado con el alcance incómodo de las expresiones de funciones con nombre.
El código es el siguiente:
función double(x){ return x*2 }
var f = function(x){ return x*; 2; }
El mismo código de función también se puede utilizar como expresión, pero tiene significados completamente diferentes. La diferencia oficial entre funciones anónimas y expresiones de funciones con nombre es que estas últimas están vinculadas a una variable con el mismo nombre de función que una variable local de la función. Esto se puede utilizar para escribir expresiones de funciones recursivas.
El código es el siguiente:
var f = función buscar(árbol, clave){
//....
return find (tree.left, key)
find(tree.right, key
}
Vale la pena señalar que el alcance; de la variable find Solo dentro de su propia función, a diferencia de una declaración de función, no se puede hacer referencia externa a una expresión de función nombrada por su nombre de función interna.
El código es el siguiente:
find(myTree, "foo"); //error: la búsqueda no está definida
var constructor = function( ){ return null }
var f= function(){
return constructor();
};
f( );/ /{}(en entornos ES3)
Parece que este programa generará un valor nulo, pero en realidad generará un nuevo objeto.
Debido a que el alcance de la variable de función nombrada hereda Object.prototype.constructor (es decir, el constructor de Object), al igual que la declaración with, este alcance se verá afectado por el cambio dinámico de Object.prototype. La forma de evitar que los objetos contaminen el alcance de las expresiones de funciones en su sistema es evitar agregar propiedades a Object.prototype en cualquier momento y evitar el uso de variables locales con el mismo nombre que las propiedades estándar de Object.prototype.
Otra deficiencia de los motores JavaScript populares es la promoción de declaraciones de expresiones de funciones con nombre.
El código es el siguiente:
var f = function g(){return 17;}
g() //17 (en entorno no conforme). )
p>Algunos entornos JavaScript incluso tratan las dos funciones f y g como objetos diferentes, lo que resulta en una asignación de memoria innecesaria.
1.6 Cuidado con las declaraciones de alcance incómodas para funciones de bloque local
El código es el siguiente:
function f() {return "global"
; p>
prueba de función(x){
función f(){return "local";}
var resultado = [];
if (x) {
resultado.push(f());
}
resultado.push(f()); > resultado resultado ;
}
prueba(verdadero); //["local","local"]
prueba(falso); "local" ]
El código es el siguiente:
función f() {return "global" }
función test(x){ p>
var resultado = [];
if(x){
función f(){return "local";}
resultado. push(f())
}
resultado.push(f()
resultado resultado; /p>
test(true); //["local", "local"]
test(false); //["local"]
Javascript lo hace no tiene alcance a nivel de bloque, por lo que el alcance de la función interna f debe ser toda la función de prueba.
Esto es cierto para algunos entornos de JavaScript, pero no todas las implementaciones de JavaScript informan funciones como errores en modo estricto (un programa en modo estricto con una declaración de función de bloque local lo informará como un error de sintaxis). -Código portátil y proporciona una semántica más sensata y confiable a las declaraciones de funciones de bloques locales para futuras versiones del estándar. Para esta situación, puede considerar declarar una variable local en la función de prueba que apunte a la función global f.