Ningún otro libro ha tenido tanto impacto en el ecosistema de JavaScript como "The Good Parts" de Douglas Crockford. The Good Parts es realmente una historia de cómo llegó la iluminación al Sr. Crockford. Ahora, Doug ha estado codificando software durante mucho tiempo, por lo tanto, tiene sentido escuchar lo que tiene que decir. Su principal argumento es que, a pesar de todos sus desagradables defectos, JavaScript tiene algunas partes realmente buenas. Si JavaScript tiene muchas partes buenas, pero también algunas malas, ¿no tiene sentido enfocarse en las partes buenas y hacer uso de ellas? ¡De hecho lo hace! Este episodio hará precisamente eso, y echa un vistazo a las partes del lenguaje JavaScript que Douglas Crockford Champions. Echemos un vistazo, ¿de acuerdo?

  • 1Objetos según Crockford
  • 2Literales de objeto
  • 3Obtener valores de objetos (recuperación)
  • 4Funciones
  • 5Creación de una función literal
  • 6Cuatro patrones de invocación
  • 7Invocación de método
  • 8Invocación de función
  • 9Invocación de constructor
  • 10Aplicar invocación
  • 11Argumentos
  • 12Excepciones
  • 13Recursividad
  • 14Alcance de JavaScript
  • 15Cierre
  • dieciséisDevoluciones de llamada
  • 17Módulos
  • 18Delegación
  • 19Matrices
  • 20Métodos JavaScript

Configuración de un entorno de desarrollo de JavaScript

Comenzar con JavaScript es posiblemente más fácil que en cualquier otro idioma en cualquier período de tiempo. En su forma más simple, simplemente abra un navegador web y navegue hasta la consola de JavaScript. Google Chrome, Mozilla Firefox y Microsoft Edge tienen herramientas de desarrollo excelentes y maduras disponibles de forma gratuita integradas en el navegador. Puede usar algo tan simple como el siguiente código para comenzar.


Objetos según Crockford

Esta sección analizará cómo Doug presenta los objetos en JavaScript y cubre los literales de objetos, recuperación, actualización, referencia, prototipo, reflexión, enumeración, eliminación y reducción global.


Literales de objeto

Es muy fácil crear un objeto literal en JavaScript. Veamos algunos ejemplos.

Puede ordenar la existencia de un objeto con una línea de código como esta.

En lugar de crear un objeto vacío, puede definir un objeto y completar algunos valores de una sola vez.

Cosas interesantes. Ahora, el lado izquierdo de cada par clave / valor se denomina propiedad. Cada propiedad debe tener algún valor correspondiente y las propiedades múltiples están separadas por comas. También puede anidar objetos muy fácilmente como tal.


Obtener valores de objetos (recuperación)

Haga clic para recuperar valores. Claro

<div id = ”valueretrieval”>

Aquí hacemos uso de la conveniente notación de puntos, sin embargo, también puede acceder a los valores usando la notación de corchetes si lo prefiere, como lo siguiente:

Si intenta acceder a un valor en una propiedad inexistente, se le devolverá undefined.

Sin embargo, puede verificar si hay un valor indefinido y completar un valor predeterminado si desea usar el ||operador.

Intentar obtener un valor de un undefinedvalor producirá un TypeError.


Funciones

Las funciones son donde ocurre la magia. Según Crockford, las funciones son lo mejor del lenguaje JavaScript. Las funciones están vinculadas a Function.prototype.


Creación de una función literal

Veamos un ejemplo de una función literal.


Cuatro patrones de invocación

Hay cuatro formas de invocar una función en JavaScript.

  • Invocación de método
  • Invocación de función
  • Invocación de constructor
  • Aplicar invocación

Invocación de método

Si una función se almacena dentro de la propiedad de un objeto, entonces se puede considerar como un método . Aquí viene la confusión: la thispalabra clave. La thisimplementación de JavaScript es lo más confuso y complicado visto entre cualquier lenguaje que implemente alguna forma de thisCuando se invoca un método, el valor de thisestá vinculado a ese objeto específico. ¿Cómo sabe si está llamando a un método? Si está utilizando un refinamiento como el .operador, entonces está llamando a un método. Veamos un ejemplo.

Haga clic para invocar un método. Claro

<div id = ”métodoinvocación”>


Invocación de función

Si una función no es una propiedad de un objeto, cuando se invoca, se hace como una función. Una función que se invoca como una función se ha thisvinculado al objeto global, normalmente el objeto Ventana. Verifiquemos esta afirmación.

Haga clic para invocar una función. Claro

<div id = "functioninvocation">


Invocación de constructor

No hay clases en JavaScript, pero puede crear nuevas instancias de objetos de manera similar a llamar a un método de construcción en lenguajes de programación orientados a objetos más tradicionales. Curiosamente, getify hace un buen punto en el sentido de que lo que comúnmente se conoce como lenguajes de programación orientados a objetos debería en realidad denominarse lenguajes de programación basados ​​en clases. En este punto, la terminología está demasiado arraigada, pero si lo piensas, tiene sentido. En el estilo clásico de programación orientada a objetos, usted crea instancias objectsque se basan en clases. JavaScript no funciona así en absoluto. En JavaScript, los objetos se derivan de otros objetos. Veamos cómo.

¡Haga clic para ver la invocación del constructor! Claro

<div id = "constructorinvocation">

Con el patrón de invocación de constructor, puede crear nuevas instancias de un objeto con la newpalabra clave. Con este enfoque, thisestá vinculado al objeto recién creado. De todos los enfoques de invocación, el patrón de invocación de constructor puede parecerle el más familiar a la mayoría de los programadores de OOP clásicos. Asegúrese de usar siempre una letra mayúscula en la variable que almacena el constructor de la función. Así es como puede determinar rápidamente cuándo una variable debe contener un constructor de JavaScript.


Aplicar invocación

Una maravilla sobre JavaScript es que las funciones pueden tener métodos. Uno de esos métodos es el applymétodo. Lo que hace es permitirnos proporcionar una matriz de argumentos para pasar a la función, además de permitirnos especificar qué objeto debe ser referenciado thisEl primer parámetro del applymétodo es a qué se thisdebe enlazar. El segundo argumento es la matriz de argumentos para pasar a la función. Veámoslo en acción.

¡Haga clic para ver Aplicar invocación! Claro

<div id = "applyinvocation">

Estos son los conceptos básicos de la invocación de funciones y cómo afecta thisSu tarea debe ser la de leer sobre thisel Mozilla Developer Network , además de leer sobre el nuevo bind () método.


Argumentos

Cuando se llaman funciones, tienen acceso a un parámetro de argumento oculto. Lo que hace es contar el número de parámetros que se pasaron a la función y proporciona acceso a esos valores. Es por eso que puede escribir una función y no tener que especificar cuántos parámetros necesita.

¡Haga clic para ver argumentos en acción! Claro

<div id = ”argumentos”>


Excepciones

Douglas Crockford no necesita usar un try-catch. Cuando Douglas Crockford escribe código, no hay excepciones. Sin embargo, resulta que JavaScript proporciona un medio eficiente para manejar excepciones. Usted no es Douglas Crockford y, como tal, puede encontrar errores. Aprenda a lidiar con estas excepciones con este ejemplo.

¡Haga clic para ver las excepciones en acción! Claro

<div id = "excepciones">


Recursividad

Casi se puede pensar en la recursividad como una forma de bucle. Una función puede llamarse a sí misma para dividir un problema en subproblemas más pequeños. Cuando se completan todos los subproblemas, la recursividad ha seguido su curso. JavaScript no tiene optimización de recursividad de cola. Lo que eso significa es que si estropea la lógica en su función recursiva, muy bien podría bloquear el entorno de programación agotando la pila de retorno. Aquí hay un ejemplo del rompecabezas de las Torres de Hanoi resuelto con recursividad.

¡Haga clic para ver la recursividad en acción! Claro

<div id = "recursividad">


Alcance de JavaScript

El alcance en JavaScript es una bestia, especialmente si está acostumbrado a establecer el alcance de reglas de otros lenguajes. Entonces, ¿qué es Scope? Bueno, es donde buscar cosas. Realmente no es mucho más complicado que eso. En JavaScript, tenemos el alcance de la función. Echemos un vistazo a un ejemplo.

Analicemos esto porque es una locura.

Primero abordaremos la fase de compilación .

  • 1. Hey alcance global, tengo una declaración para una variable llamada factEl alcance global dice: "Lo tengo, puedes seguir adelante".
  • 2. Oye alcance global. Tengo una función llamada roundhouse()y quiero registrarlo en el alcance global. El alcance global cumple con esta solicitud y roundhouse()ahora está registrado en el alcance global.
  • 3. Ahora descendemos a la función roundhouse y decimos, oye alcance roundhouse, tengo una declaración para la variable llamada factRoundhouse de alcance de función ahora tiene esta variable declarada.
  • 4. Todavía estamos en el alcance de roundhouse () y ahora nos encontramos con una jslint()función. ¿Así que lo que ocurre? Hola alcance roundhouse (), tengo una declaración de función para la función jslint (). Scope of roundhouse () responde y dice genial, lo tengo registrado.
  • 5. Ahora descendemos al ámbito jslint (). Hola alcance de jslint (), tengo una declaración de variable implícita para un hecho. El alcance de jslint () responde y dice ok, tienes tu variable de hechos declarada.

Ahora, solo milisegundos después, pasamos por la fase de ejecución .

  • 1. Oye, alcance global, tengo un LHS (Referencia de mano izquierda) para una variable llamada fact¿has oído hablar de él? El alcance global responde: "Sí, claro que sí, aquí está la referencia a esa variable". En ese momento, el valor de "Doug Crockford puede retroceder en el tiempo como Superman, como hizo con ES4 para llegar a ES5". se asigna inmediatamente a la factvariable en el ámbito global .
  • 2. En este punto durante la fase de ejecución, saltamos directamente a la llamada a roundhouse()Las líneas anteriores que fueron atendidas durante la fase de compilación.
  • 3. Oye, alcance global. Tengo un RHS (Referencia de la mano derecha) para una variable llamada Roundhouse, ¿has oído hablar de él? El alcance global responde, "claro, lo tengo, aquí tienes, aquí tienes una referencia a esa variable". Ahora, podemos recuperar ese valor y encontramos que es un objeto de función. También vemos que el operador de invocación sigue inmediatamente a roundhouse, por lo que ejecutamos esa función.
  • 4. Oye alcance de roundhouse () , tengo una referencia LHS para una variable llamada fact, ¿has oído hablar de él? El telescopio circular responde: "Seguro que he oído hablar de él, aquí está la referencia a esa variable". Ahora tenga en cuenta que esta es la factvariable que vive en el alcance de la casa circular , * no en el alcance global *. Con eso, el valor de 'Douglas Crockford no duerme, espera que lo activen'. se asigna a la factvariable en el alcance de la rotonda.
  • 5. En este punto, saltamos a la llamada a jslint()y es algo como esto. "Oye, alcance de roundhouse (), tengo una referencia de RHS para una variable llamada jslint , ¿has oído hablar de él? El alcance de roundhouse () responde:" Sí, aquí está la referencia a esa variable ". Luego encontramos su valor , y encontrar que es un objeto de función y luego ejecutarlo inmediatamente.
  • 6. Luego pasamos al alcance de jslint () y la conversación es así. Hola alcance de jslint () Tengo una referencia LHS para una variable nombrada fact, ¿has oído hablar de él? El alcance de jslint () responde y dice: "Sí, de hecho, aquí está la referencia a esa variable". Esto es cierto porque factse declaró como un parámetro con nombre. En este punto, la cadena 'Si ejecuta "typeof Crockford", su navegador devolverá "impresionante"' se asigna facten el alcance de jslint () .
  • 7. Ahora pasamos a la siguiente línea y decimos, hey scope of jslint, tengo una referencia LHS para una variable nombrada amazing¿has oído hablar de él? El alcance de jslint responderá con: "Nunca he oído hablar de esta variable de la amazingque hablas, ve a pescar". Lo que esto significa es que, dado que este alcance no tiene lo que está buscando, busque en el siguiente alcance. Entonces eso es lo que hacemos. Hola alcance de roundhouse (), tengo una referencia LHS para una variable nombrada amazing, ¿alguna vez escuché de él? El alcance de la casa circular ahora responderá con "Nunca he oído hablar de esta variable de la amazingque hablas, ve a pescar". Ok, sigamos. Ahora estamos en el ámbito global. Hey, alcance global tengo una referencia LHS para una variable llamadaamazing¿Alguna vez has oído hablar de él? El alcance global ahora responderá con: "Nunca he oído hablar de esta variable de la amazingque hablas, pero como me gustas, crearé una para ti como por arte de magia, aquí está tu referencia a esa variable". Simplemente así, ha creado una nueva variable en el ámbito global, que puede que no haya tenido la intención de hacerlo.

¡Haga clic para ver el alcance en acción! Claro

<div id = "alcance">


Cierre

El cierre depende del alcance léxico. Para comprender realmente el cierre, primero debe comprender el alcance léxico. El alcance léxico es la comprensión de declarar variables dentro de su alcance dado y está escrito en piedra al momento de la compilación. El ámbito léxico establece que las variables que pertenecen a este ámbito de función no pertenecen a ese ámbito de función. El autor del software toma la decisión de antemano qué variables pertenecerán a qué alcance.

Entonces, ¿qué es el cierre? La definición de getify es la que mejor lo resume.

El cierre es cuando una función recuerda su alcance léxico incluso cuando la función se ejecuta fuera de ese alcance léxico.

Sé que dedicamos este artículo a Crockford, pero Getify podría ser el próximo Crockford, así que debemos adaptarnos a los tiempos. Veamos un código de ejemplo.

Aquí tenemos una función externa nombrada crockford(), y él tiene una variable nombrada facten su alcance.

Hay una función interna llamada nunchucks()que tiene su propia burbuja de alcance, que vive dentro de la burbuja de alcance de crockford(), es un alcance anidado.

Luego tomamos una referencia a la función nunchucks()y la pasamos como parámetro a una swing()función que vive fuera de la burbuja de alcance de ambos nunchucks()crockford().

Cuando la nunchucks()función en la línea 12 se ejecuta fuera del alcance donde se definió , todavía tiene acceso a las variables contenidas en el alcance léxico donde se definió originalmente. De hecho, esto es un cierre.

¡Haga clic para ver el cierre en acción! Claro

<div id = "cierre">

Veamos otro ejemplo de cierre. Este es del libro The Good Parts.

Veamos cómo este código es un ejemplo de cierre. Comenzamos llamando a la fade()función y pasamos un elemento dom. fade()lo establece levelen uno y define una función step (). fade()luego llama a la setTimeout()función con la step()función como primer parámetro y 100 milisegundos como segundo. La fade()función regresa y ha terminado de ejecutarse. fade()ya está hecho.

100 milisegundos después, se step()vuelve a invocar. Para hacer su trabajo, necesita tener acceso a la levelvariable que pertenece al fade()alcance. Recuerde, fade() ya se ha ejecutado y regresado , es un recuerdo en este punto. Sin levelembargo, es variable , siempre que la función interna lo step()necesite para hacer su trabajo. Vea este ejemplo de buena pieza de Crockford:

¡Haga clic para ver el cierre2 en acción!

<div id = "cierre2">

Douglas Crockford puede leer tu mente con un cierre de cinco forros


Devoluciones de llamada

Las devoluciones de llamada también se conocen como funciones de orden superiorEsto quiere decir que una devolución de llamada es una función que se pasa a otra función como parámetro, y esa función pasada se llama o ejecuta dentro de la función a la que se le pasó, por lo general, después de que se cumple una condición, o después de un conjunto período de tiempo. Es muy popular en JavaScript, tanto que lo llamamos patrón de devolución de llamada.

Veamos un ejemplo en el que configuramos dos funciones. Primero creamos un callbackfunction()que envía un texto a la pantalla cuando se ejecuta. Luego creamos un al firstfunction()que pasamos dos parámetros. El primer parámetro es un texto como mensaje que firstfunction()se utilizará para enviar al navegador. También pasamos callbackfunctioncomo segundo argumento a firstfunction()Finalmente, adjuntamos un evento de clic a un botón para ejecutar el firstfunction()cuando se hace clic. Mira los resultados.

¡Haga clic para ver la devolución de llamada en acción! Claro

<div id = "devolución de llamada">

Notarás que la única función que nosotros, como usuario, realmente activamos fue firstfunction(), sin embargo, tanto la salida firstfunction()como callbackfunction()aparecen en la pantalla gracias al patrón de devolución de llamada. Estos son los conceptos básicos de una devolución de llamada, y es digno de artículos completos por sí solo. La conclusión, sin embargo, es que cuando pasa una función como argumento a otra función, está haciendo uso de una devolución de llamada.

Las devoluciones de llamada pueden ser un poco complicadas, así que veamos un ejemplo más.

¡Haga clic para ver la devolución de llamada en acción! Claro

<div id = "callback2">


Módulos

El patrón de módulo clásico es uno de los patrones más utilizados en todo JavaScript. Tiene un par de características que lo convierten en un módulo. La primera característica es que el módulo debe tener una función de envoltura externa que se ejecute. La segunda característica es que tiene que haber al menos una función interna que se devuelve y mantiene un cierre sobre el estado interno. El propósito del patrón del módulo es proporcionar un mecanismo para emular conceptos de programación tradicionales basados ​​en clases al ofrecer la capacidad de incluir métodos y variables públicos y privados dentro de un solo objeto, lo que le permite determinar qué información le gustaría exponer a los consumidores del módulo.

Este patrón hace uso de cierres para brindar esta idea de privacidad y estado. Solo debe devolver la API pública del módulo, dejando todos los demás métodos y variables privados dentro del módulo. ¡Podemos ver cómo esto puede resultar confuso! Antes de que pueda comprender los módulos, debe comprender los cierres. Antes de que comprenda el cierre, debe tener el alcance léxico en frío. Entonces, si no hace clic de inmediato, regrese y revise el alcance léxico, luego el cierre y luego vuelva a visitar los módulos. Veamos un ejemplo.

¡Haga clic para ver los módulos en acción! Claro

<div id = "moduleex">

Hay * mucho * más en los módulos, pero esta sección nos dio una idea de para qué se usa el patrón de módulo en JavaScript y cómo podríamos construir nuestros propios módulos.


Delegación

Esta parte se iba a llamar Herencia, pero la verdad es que en JavaScript este mecanismo está mucho más basado en la delegación que en la herencia. La idea clave es que los objetos en JavaScript no tienen tanto herencia como enlaces a un prototipo.JavaScript no tiene clases y, por lo tanto, es posible que se pregunte cómo podría incluso hacer programación orientada a objetos. Bueno, en JavaScript, los objetos se vinculan a la cadena de prototipos. Todos los objetos en JavaScript son creados por una función constructora. Este nuevo objeto no se basa en el prototipo, está vinculado al prototipo. Recuerde el alcance léxico donde si tiene una función interna para la cual el compilador no puede encontrar una referencia a una variable en su alcance, se moverá fuera de su burbuja, por así decirlo, al siguiente nivel externo y solicitará a ese alcance externo una referencia a esa variable. Esto continúa hasta que finalmente se alcanza el alcance global, y si no hay una referencia de variable allí, se crea una (en modo no estricto).

Cada objeto en JavaScript es creado por una función constructora. Cada vez que se llama a una función de constructor, se crea un objeto nuevo de la nada. No es un objeto en la forma en que pensaría en términos de programación clásica orientada a objetos, sino más bien un objeto que se vincula de nuevo a su propio prototipo. Veamos cómo funciona esto en un ejemplo.

¡Haga clic para ver las delegaciones en acción! Claro

<div id = "delegaciónex">

Antes de que este código se ejecute, hay algunas cosas que suceden automáticamente en JavaScript. Primero, hay una función llamada ObjetoTambién hay un objeto al que está vinculada esta función que se llama Object.prototypeEsos dos recursos deben leerse en su totalidad para comprender lo que está sucediendo en el código de ejemplo anterior. De hecho, el concepto de orientación de objetos necesita un artículo completo o incluso un libro para cubrirlo por completo. Todo lo que queremos entender aquí es que cuando se llama a un método en un objeto si ese objeto en particular no tiene el método en cuestión, entonces comenzará a subir por la cadena del prototipo.para encontrar una instancia de ese método. Esto está en contradicción directa con la forma en que las clases tradicionales transmiten métodos a sus hijos. En JavaScript, los objetos verifican sus vínculos de prototipo, no buscan una clase principal para su funcionalidad. Entonces, cuando vemos la llamada a Person1.greet()Person2.greet(), podemos ver que esas funciones hacen uso de una myname()función. Ni el objeto Person1 ni Person2 tienen una myname()función definida en ellos. Entonces, lo que sucede en este ejemplo cuando se ejecutan es que necesitan ascender en la cadena del prototipo para encontrar esa myname()función. Dado que cada objeto Person tiene un enlace a Person.prototype , podemos ver que el prototipo tiene una función nombrada myname()Entonces podemos decir que estos nuevos objetos están delegando la responsabilidad de llamar almyname()función a su prototipo. Es como decir: "Oye amigo, estoy tratando de completar esta tarea y no sé cómo hacerlo, ¿puedes echarme una mano?"


Matrices

Douglas Crockford se refiere a Arrays en JavaScript como un objeto que tiene características similares a una matriz, como si dijera que no es realmente una matriz. La razón de esto es que JavaScript convierte los subíndices de la matriz en cadenas, y esas cadenas se convierten en propiedades del objeto. Obtener y establecer valores desde y hacia matrices funciona igual que obtener y establecer valores en objetos. Veamos cómo crear un Array Literal aquí.

¡Haga clic para ver matrices en acción! Claro

<div id = "arrayex">

Como puede ver, podemos asignar cualquier tipo que queramos a una ranura de matriz. En nuestro ejemplo, colocamos una cadena, función, objeto, número, un par de valores booleanos, una matriz, nulo, indefinido y NaN en nuestra matriz. En uno de los efectos extravagantes de JavaScript, si aplica un operador typeof a todos estos, puede ver que casi todo es un objeto, excepto NaN, que en realidad no está definido. JavaScript!

La propiedad length es bastante útil en JavaScript y se usa a menudo en bucles. Veamos cómo.

Haga clic para ver array.length en acción! Claro

<div id = "arrayex2">

JavaScript también tiene una for inconstrucción de bucle, pero Douglas Crockford aboga por seguir el forbucle estándar que existe en todos los lenguajes basados ​​en C. El problema for ines que puede producir resultados en un orden inesperado o puede extraer propiedades inesperadas de la cadena de prototipos. El forbucle es una buena parte.

Las matrices y los objetos están tan estrechamente relacionados en JavaScript que puede resultar confuso cuándo utilizar uno u otro. Doug nos da esta práctica regla:

Cuando los nombres de las propiedades son pequeños enteros secuenciales, debe usar una matriz. De lo contrario, use un objeto. Douglas Crockford

Métodos JavaScript

JavaScript tiene una pequeña colección de métodos integrados en el lenguaje que facilitarán su desarrollo. En un lenguaje como PHP, tiene literalmente miles y miles de funciones integradas en el lenguaje. En cierto sentido, PHP es su propio marco. JavaScript no tiene una colección tan masiva de funciones integradas. Quizás es por eso que hay más marcos de JavaScript de los que puedas imaginar. La gente está tratando de incorporar al lenguaje toda la riqueza de características que se requieren para el desarrollo web. En cualquier caso, le será de gran utilidad estar familiarizado con los métodos integrados del lenguaje. Aquí están los enlaces a los que desea conocer.

  • Métodos de matriz

  • Métodos de función

  • Métodos numéricos

  • Métodos de objetos

  • Métodos RegExp

  • Métodos de cadena

Douglas Crockford Resumen de ejemplos de piezas buenas

Este tutorial de JavaScript se centró vagamente en las enseñanzas de Douglas Crockford en su ahora famoso libro JavaScript The Good Parts. La pasamos bien revisando algunos conceptos importantes como Literales de objeto, Obtención de valores de objetos, Funciones, Creación de un literal de función, Cuatro patrones de invocación, Invocación de método, Invocación de función, Invocación de constructor, Aplicar invocación, Argumentos, Excepciones, Recurrencia, Alcance de JavaScript , Closure, Callbacks, Módulos, Delegación, Arrays y Métodos JavaScript.