Quiero escribir una biblioteca de clase JavaScript eficiente pero no puedo comenzar;
Intenta leer la biblioteca de otras personas, pero compruélvala como si se entienda;
Planeo estudiar bien las funciones JS avanzadas, pero el contenido en el libro autorizado está demasiado disperso.
Incluso si recuerda el "uso", no piensa en el "método" cuando desea "usar".
Tal vez usted, como yo, parezca tener una fuerza invisible que restringe nuestros planes, haciéndonos pensar repetidamente que las limitaciones del conocimiento nos han hecho detenernos y difíciles de avanzar.
Durante este período, se han duplicado varias tareas, diseño de cursos e informes experimentales. Es raro exprimir un poco de tiempo, nunca dormir, y ordenar los libros que he leído en el pasado solo para estar más cerca de escribir mi propia biblioteca.
Este artículo se hace referencia a "JavaScript Language Essence" y "JavaScript efectivo". Todos los ejemplos han sido depurados. Después de entenderlos, quiero hacer que algunos principios "profundos" sean un poco más simples.
1. Alcance variable
El alcance es como oxígeno para los programadores. Está en todas partes, y ni siquiera piensas en ello. Pero cuando está contaminado (como el uso de objetos globales), se sentirá ahogable (como la respuesta de aplicación lenta). Las reglas de alcance de JavaScript Core son simples, cuidadosamente diseñadas y muy poderosas. El uso efectivo de JavaScript requiere dominar algunos de los conceptos básicos de alcance variable y comprender algunas situaciones extremas que pueden conducir a problemas esquivos y molestos.
1.1 Intente usar variables globales lo menos posible
JavaScript es fácil de crear variables en un espacio de nombres global. La creación de variables globales es fácil porque no requiere ninguna forma de declaración y todo el código de todo el programa puede acceder automáticamente.
Para nosotros, principiantes, al encontrar ciertas necesidades (por ejemplo, cuando se registran los datos transmitidos, esperando que se llame un cierto tiempo, o cuando se usa una determinada función a menudo), finalmente pensamos en funciones globales. Incluso el pensamiento orientado al proceso del lenguaje C que aprendí en mi primer año está demasiado arraigado, y el sistema está perfectamente lleno de funciones. La definición de las variables globales puede contaminar espacios de nombres públicos compartidos y puede conducir a conflictos de nombres inesperados. Las variables globales tampoco conducen a la modularidad, ya que causa un acoplamiento innecesario entre componentes independientes en el programa. Hablar en serio, demasiada global (incluidas las hojas de estilo, definir directamente los estilos de div o a) e integrarlas en los desarrollos de varias personas será un error catastrófico. Esta es la razón por la cual todo el código jQuery está envuelto en una expresión anónima ejecutada instantáneamente: las funciones anónimas de autónomo. Cuando el navegador carga el archivo jQuery, comienza a la ejecución inmediatamente después de llamar a la función anónima, inicializando varios módulos de jQuery para evitar destruir y contaminar variables globales y afectar otros códigos.
La copia del código es la siguiente:
(función (ventana, indefinida) {
var jQuery = ...
// ...
Window.jquery = Window. $ = jQuery;
})(ventana);
Además, puede pensar que es más conveniente "escribir cómo lo primero y organizarlo más tarde", pero los excelentes programadores prestarán constantemente atención a la estructura del programa, clasificar continuamente las funciones relacionadas y los componentes irrelevantes separados, y estos comportamientos son parte de la fórmula de programación.
Dado que los espacios de nombres globales son la única forma de que interactúen los componentes independientes en los programas de JavaScript, el uso de controles globales de nombres es inevitable. Los componentes o bibliotecas deben definir algunas variables globales. Para su uso por otras partes del programa. De lo contrario, es mejor usar variables locales.
La copia del código es la siguiente:
this.foo; // Undefinado
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 está expuesto a objetos globales a los que se puede acceder en el alcance global del programa, que sirve como el valor inicial de esta palabra clave. En un navegador web, el objeto global está vinculado a la variable de ventana global. Esto significa que hay dos formas de crear una variable global: declararla con VAR dentro del alcance global o agregarlo al objeto global. La ventaja de usar declaraciones de VAR es que pueden expresar claramente el impacto de las variables globales en el alcance del programa.
Dado que las referencias a las variables globales vinculadas pueden causar errores de tiempo de ejecución, los ámbitos de ahorro claro y conciso facilitarán que los usuarios de código comprendan las variables globales que declara el programa.
Dado que el objeto global proporciona un mecanismo de respuesta dinámica para el entorno global, se puede utilizar para consultar un entorno en ejecución y detectar qué características están disponibles en esta plataforma.
EG.ES5 presenta un objeto JSON global para leer y escribir datos de formato JSON.
La copia del código es la siguiente:
if (! this.json) {
this.json = {
Parse: ..,
Stringify: ...
}
}
Si proporciona una implementación de JSON, por supuesto, puede usar simplemente e incondicionalmente su propia implementación. Pero las implementaciones incorporadas proporcionadas por el entorno de host son casi más adecuados porque están escritas en el navegador en C. porque verifican estrictamente la precisión y la coherencia de acuerdo con ciertos estándares y generalmente proporcionan un mejor rendimiento que las implementaciones de terceros.
La operación básica de las cadenas de simulación de diseño del curso de estructura de datos requería que no se pudieran utilizar los métodos proporcionados por el lenguaje en sí. JavaScript implementa muy bien las operaciones básicas de las matrices. Si es solo para las necesidades generales de aprendizaje, la idea de los métodos de simulación proporcionados por el lenguaje en sí es bueno, pero si realmente invierte en desarrollo, no necesita considerar elegir utilizar los métodos incorporados de JavaScript lo antes posible.
1.2 Evite usar con
La instrucción With proporciona cualquier "conveniencia" que haga que su aplicación sea poco confiable e ineficiente. Necesitamos llamar a una serie de métodos en un solo objeto a su vez. El uso de la instrucción With puede evitar fácilmente las referencias duplicadas a los objetos:
La copia del código es la siguiente:
Estado de la función (info) {
var widget = new Widget ();
con (widget) {
Sackbackground ("Azul");
setForefround ("blanco");
setText ("estado:"+info);
espectáculo();
}
}
También es muy tentador usar la instrucción con "importar" (importar) variables de un objeto de módulo.
La copia del código es la siguiente:
función f (x, y) {
con (matemáticas) {
return min (redondo (x), sqrt (y)); // cita abstracta
}
}
De hecho, JavaScript trata todas las variables de la misma manera. JavaScript comienza desde el alcance más interno y busca variables hacia afuera. El lenguaje con el lenguaje trata un objeto como si represente un alcance variable, por lo que dentro del bloque con código, las búsquedas variables comienzan buscando atributos del nombre variable dado. Si la propiedad no se encuentra en este objeto, continúe buscando en el alcance externo. La referencia a cada variable externa en el bloque con el bloque supone implícitamente que no hay atributo con el mismo nombre en el objeto con el objeto (y cualquiera de sus objetos prototipo). La creación o modificación de un objeto con su prototipo en otra parte del programa no sigue necesariamente tales supuestos. El motor JavaScript ciertamente no lee el código local para obtener las variables locales que está utilizando. El alcance de JavaScript se puede representar como estructuras de datos internos eficientes, y las búsquedas variables son muy rápidas. Sin embargo, dado que el bloque con código con el código necesita buscar la cadena prototipo del objeto para encontrar todas las variables en el código con código, su velocidad de ejecución es mucho más baja que la del bloque de código general.
En lugar del lenguaje con el lenguaje, es simple vincular el objeto a un nombre de variable corto.
La copia del código es la siguiente:
Estado de la función (info) {
var w = new Widget ();
W.SetBackground ("Azul");
W.SetForefround ("White");
W.Settext ("Estado:"+info);
w.show ();
}
En otros casos, la mejor manera es vincular explícitamente las variables locales a propiedades relevantes.
La copia del código es la siguiente:
función f (x, y) {
var min = math.min,
Round = Math.round,
sqrt = math.sqrt;
return min (redondo (x), sqrt (y));
}
1.3 Competente en cierre
Hay un solo concepto para comprender los cierres:
a) JavaScript le permite hacer referencia a variables definidas fuera de la función actual.
La copia del código es la siguiente:
función MakesAndwich () {
var mágica mágica = "mantequilla de maní";
función de función (relleno) {
devolver MAILDRECREDENT + "y" + relleno;
}
regresar make ("gelatina");
}
Makesandwich (); // "Mantequilla de maní y gelatina"
b) Incluso si la función externa ha regresado, la función actual aún puede referirse a la variable definida por la función externa.
La copia del código es la siguiente:
función MakesAndwich () {
var mágica mágica = "mantequilla de maní";
función de función (relleno) {
devolver MAILDRECREDENT + "y" + relleno;
}
regresar hacer;
}
var f = sandwichmaker ();
f ("gelatina"); // "Mantequilla de maní y gelatina"
f ("plátanos"); // "Mantequilla de maní y plátanos"
f ("Mallows"); // "Mantequilla de maní y maletas"
Los valores de función de JavaScriptd contienen más información que el código requerido para ejecutar cuando se les llama. Además, los valores de la función de JavaScript también almacenan internamente las variables a las que pueden referirse definidas en su alcance cerrado. Esas funciones que rastrean las variables dentro del alcance que cubren se llaman cierres.
La función Make es un cierre cuyo código se refiere a dos variables externas: MagingRededient y relleno. Cada vez que se llama a la función Make, su código puede referirse a estas dos variables porque el cierre almacena estas dos variables.
Una función puede referirse a cualquier variable dentro de su alcance, incluidos los parámetros y las variables de función externas. Podemos usar esto para escribir más funciones generales de sándwichmaker.
La copia del código es la siguiente:
función MakeAndwich (MagingRededient) {
función de función (relleno) {
devolver MAILDRECREDENT + "y" + relleno;
}
regresar hacer;
}
var f = sandwichmaker ("jamón");
f ("queso"); // "jamón y queso"
f ("mostaza"); // "jamón y mostaza"
Los cierres son una de las características más elegantes y expresivas de JavaScript y también son el núcleo de muchos modismos.
c) El cierre puede actualizar el valor de una variable externa. De hecho, los cierres almacenan referencias a variables externas, no copias de sus valores. Por lo tanto, se puede actualizar cualquier cierre con acceso a estas variables externas.
La copia del código es la siguiente:
function box () {
var val = indefinido;
devolver {
set: function (newVal) {val = newval;},
get: function () {return val;},
Tipo: function () {return typeOf val;}
};
}
var b = box ();
B.Type (); //indefinido
B.Set (98.6);
B.get (); // 98.6
b.type (); // número
Este ejemplo produce un objeto que contiene tres cierres. Estos tres cierres se establecen, escriben y obtienen propiedades, y todos comparten acceso a las variables VAL, y el cierre establecido actualiza el valor de Val. Luego llame a obtener y escriba para ver los resultados actualizados.
1.4 Comprender la mejora de la declaración variable
JavaScript admite este alcance del método (las referencias a la variable FOO estarán vinculadas al alcance que declara la variable FOO más cercana), pero no admite el alcance de nivel de bloque (el alcance definido por la variable no es la declaración cerrada más cercana o el bloque de código).
No entender esta característica conducirá a algunos errores sutiles:
La copia del código es la siguiente:
función iswinner (jugador, otros) {
var más alto = 0;
para (var i = 0, n = otros.length; i <n; i ++) {
Var jugador = otros [i];
if (jugador.score> más alto) {
más alto = jugador.score;
}
}
return player.score> más alto;
}
1.5 Tenga cuidado con el alcance torpe de las expresiones de la función de nomenclatura
La copia del código es la siguiente:
función doble (x) {return x*2; }
var f = función (x) {return x*2; }
La misma pieza de código de función también se puede usar como expresión, pero tiene significados completamente diferentes. La diferencia oficial entre las funciones anónimas y las expresiones de funciones nombradas es que esta última está unida a una variable con el mismo nombre de función que su nombre de función, que sirve como una variable local de la función. Esto se puede usar para escribir expresiones de funciones recursivas.
La copia del código es la siguiente:
var f = function find (tree, key) {
// ...
return find (tree.left, key) ||
encontrar (árbol.rright, llave);
}
Vale la pena señalar que el alcance de la variable encontrar es solo en su propia función. A diferencia de las declaraciones de la función, las expresiones de función nombradas no se pueden hacer referencia externamente a través de su nombre de función interna.
La copia del código es la siguiente:
encontrar (mytree, "foo"); // error: encontrar no está definido;
var constructor = function () {return null; }
var f = function () {
return constructor ();
};
f (); // {} (en entornos ES3)
Parece que el programa producirá nulo, pero en realidad producirá un nuevo objeto.
Debido a que la variable de función nombrada hereda objeto.prototype.constructor (es decir, el constructor de oject), al igual que con las declaraciones, este alcance se verá afectado por los cambios dinámicos de objeto.prototype. La forma de evitar que el objeto contamine el alcance de las expresiones de función en el sistema es evitar agregar propiedades en el objeto. Prototipo en cualquier momento para evitar el uso de cualquier variables locales con el mismo nombre que la propiedad de Object.Prototype estándar.
Otra desventaja en el popular motor JavaScript es la promoción de la declaración de expresiones de funciones nombradas.
La copia del código es la siguiente:
var f = function g () {return 17;}
gramo(); // 17 (en entorno no conformado)
Algunos entornos de JavaScript incluso usan las dos funciones F y G como objetos diferentes, lo que resulta en una asignación de memoria innecesaria.
1.6 Tenga cuidado con el alcance torpe para las funciones de bloques locales
La copia del código es la siguiente:
función f () {return "global"; }
prueba de función (x) {
función f () {return "local";}
resultado var = [];
if (x) {
resultado.push (f ());
}
resultado.push (f ());
Resultado del resultado;
}
prueba (verdadero); // ["local", "local"]
prueba (falso); //["local"]
La copia del código es la siguiente:
función f () {return "global"; }
prueba de función (x) {
resultado var = [];
if (x) {
función f () {return "local";}
resultado.push (f ());
}
resultado.push (f ());
Resultado del resultado;
}
prueba (verdadero); // ["local", "local"]
prueba (falso); //["local"]
JavaScript no tiene un alcance de nivel de bloque, por lo que el alcance de la función interna F debe ser toda la función de prueba. Algunos entornos JavaScript sí, pero no todos los entornos JavaScript. Las implementaciones de JavaScript informan funciones como errores en modo estricto (programas en modo estricto con declaraciones de función de bloqueo local informarán como un error de sintaxis), lo que ayuda a detectar código no portátil, dando declaraciones de función de bloque de bloque más sabias y posibles para futuras versiones estándar estándar. En este caso, es posible considerar declarar una variable local dentro de la función de prueba para apuntar a la función global f.