Preguntas y respuestas de JavaScript

Recientemente, SmartSpate decidió recopilar preguntas sobre JavaScript y responderlas. El material, cuya traducción publicamos, contiene un poco más de dos docenas de preguntas sobre JavaScript y las respuestas a ellas. La gama de temas cubiertos aquí es bastante amplia. En particular, estas son características del lenguaje, problemas encontrados por los programadores al escribir código JS, trabajar en el navegador y en el Node.js.



Pregunta número 1. Herencia prototipo


Me acostumbré a las clases "clásicas", pero decidí aprender JavaScript. Tengo un problema para entender el modelo prototipo. Si es posible, explique, en forma de plantillas, la capacidad de crear "clases" en JavaScript, cuéntenos sobre los métodos privados y abiertos y las propiedades de las clases. Entiendo que ya se ha escrito mucho sobre esto, y que en JavaScript, los métodos y propiedades de los objetos están, de manera predeterminada, a disposición del público, pero me gustaría entender todo esto correctamente. ¿Cómo funciona la herencia de prototipos en JavaScript?

▍ respuesta


La herencia clásica recuerda mucho cómo las personas heredan los genes de sus antepasados. Las personas tienen algunas habilidades básicas comunes, como caminar y hablar. Además, cada persona tiene algunas peculiaridades. Las personas no pueden cambiar lo que se puede llamar su "clase", pero pueden cambiar sus propias "propiedades" dentro de ciertos límites. Al mismo tiempo, los abuelos, las madres y los padres no pueden influir en los genes de los hijos o nietos en el proceso de su vida. Entonces, todo está organizado en la Tierra, pero imaginemos otro planeta en el que los mecanismos de herencia funcionan de manera especial. Digamos que algunos organismos capaces de mutaciones usan los mecanismos de "herencia telepática" allí. Esto se expresa en el hecho de que pueden cambiar la información genética de sus propios descendientes en el proceso de su vida.

Considere el ejemplo de herencia en este extraño planeta. El objeto Padre hereda genes del objeto Abuelo, y el objeto Hijo hereda información genética del Padre. Cada habitante de este planeta puede mutar y cambiar libremente los genes de sus descendientes. Por ejemplo, en "Abuelo" la piel tiene un color verde. Este signo es heredado por el "Padre" y el "Hijo". De repente, "Abuelo" decide que está cansado de ser verde. Ahora quiere ser azul y cambia el color de su piel (en términos de JS - cambia el prototipo de su clase), pasando "telepáticamente" esta mutación al "Padre" y al "Hijo". Después de eso, el "Padre", creyendo que el "Abuelo" había sobrevivido de la mente, decide cambiar sus genes para volverse verde nuevamente (es decir, cambia su propio prototipo). Estos cambios se transmiten "telepáticamente" al "Hijo". Como resultado, tanto el "Padre" como el "Hijo" vuelven a tener la piel verde. Al mismo tiempo, "Abuelo" sigue siendo azul. Ahora, no importa lo que haga con su color, no afectará a nadie más. Y todo esto se debe al hecho de que el "Padre" estableció explícitamente el color de su piel en su "prototipo", y el "Hijo" hereda este color. Entonces el "Hijo" piensa de esta manera: "Me volveré negro. Y que mis descendientes hereden el color de mi padre. Para hacer esto, cambia su propia propiedad (y no la propiedad de su prototipo) de tal manera que su propiedad afectaría su color, pero no afectaría a sus descendientes. Expresamos todo esto en forma de código:

var Grandfather = function () {}; //  Grandfather Grandfather.prototype.color = 'green'; var Father = function () {}; //  Father Father.prototype = new Grandfather (); //  - ,        var Son = function () {}; //  Son Son.prototype = new Father (); // Son   Father var u = new Grandfather (); //   Grandfather var f = new Father (); //   Father var s = new Son (); //   Son //     console.log ([u.color, f.color, s.color]); // ["green", "green", "green"] //  Grandfather        Grandfather.prototype.color = 'blue'; console.log ([u.color, f.color, s.color]); // ["blue", "blue", "blue"] //  Father      -   ,     Father.prototype.color = 'green'; //      : // Grandfather.prototype.color = 'green'; console.log ([u.color, f.color, s.color]); // ["blue", "green", "green"] // ,        Grandfather     color,      Grandfather.prototype.color = 'blue'; console.log ([u.color, f.color, s.color]); // ["blue", "green", "green"] //  Son,  ,       Grandfather,    s.color = 'black'; //        console.log ([u.color, f.color, s.color]); // ["blue", "green", "black"] var SonsSon = function () {}; //  SonsSon -   Son SonsSon.prototype = new Son (); //  var ss = new SonsSon (); //   SonsSon //         console.log ([u.color, f.color, s.color, ss.color]); // ["blue", "green", "black", "green"] 

Pregunta número 2. Crear objetos


Si crea nuevas instancias de objetos con la new palabra clave, ¿cómo puede protegerse de los errores? Así es como suelo trabajar:

  1. Siempre construyo funciones de constructor para que comiencen con una letra mayúscula.
  2. Verifico la corrección de la operación usando la construcción de this instanceof Function_Name (trato de no usar la construcción del tipo this instanceof arguments.callee por razones de rendimiento).
  3. Este enfoque es similar al anterior, pero la comparación se realiza con window , porque no me gusta codificar los nombres de las entidades y no es necesario escribir código para entornos que no sean el navegador.

¿Cuál es el modelo más conveniente para crear objetos?

▍ respuesta


Es mejor, tanto ideológicamente como en base a la familiaridad de este método, crear objetos utilizando la new palabra clave. En este caso, las funciones del constructor deben tener nombres que comiencen con una letra mayúscula.

Prefiero apegarme a las reglas y no realizar verificaciones adicionales en los constructores. Si se llama al constructor sin new y el trabajo comienza en el ámbito global, esto se puede comparar con el "autoengaño". Al mismo tiempo, de ninguna manera recomiendo que manejes situaciones en diseñadores donde se les llama sin la new palabra clave. Por ejemplo, puede verse así: si se llama al constructor sin new , entonces, de todos modos, se crea y devuelve un nuevo objeto. Este enfoque es ideológicamente incorrecto y conduce a errores.
Aquí hay un ejemplo de trabajo con un constructor.

 var Obj = function () {   "use strict";   this.pew = 100; }; //  let o = new Obj(); o.pew++; console.log(o.pew); //101 // .   Obj (); // TypeError: this is undefined 

Es mejor no usar la new palabra clave para los métodos de fábrica y para los casos en que no sea necesario un constructor, cuando sea más conveniente crear un objeto usando un objeto literal. Digamos que el código de constructor que se muestra en el siguiente ejemplo es explícitamente redundante:

 //    . var Obj = function () {    if (! (this instanceof Obj)) {        return new Obj ();    }    this.pew = 100; }; 

Si, incluso para crear un objeto pequeño, todavía necesita un constructor, es mejor hacer esto:

 var Obj = function () {    "use strict";    this.pew = 100; }; 

Aquí, como se muestra arriba, debido al hecho de que el constructor funciona en modo estricto, se producirá un error al llamarlo sin new .

Pregunta número 3. Intercepción de clics del mouse


¿Cómo, usando JavaScript, saber en qué botón del mouse se hace clic?

▍ respuesta


Al hacer clic en los botones del mouse, se generan eventos de mousedown y mouseup . En este caso, el evento de click se genera solo con el botón izquierdo del mouse. En el controlador de eventos, debe verificar el código ubicado en la propiedad event.button para averiguar qué botón se presiona (0 - izquierda, 1 - central, 2 - derecha). Sin embargo, en IE todo se ve un poco diferente. Considere un ejemplo:

 var button = document.getElementById ('button'),              // 0 1 2    buttonMap = ['Left', 'Middle', 'Right'],    handler = function (event) {        event = event || window.event;        alert (buttonMap [event.button] + 'id:' + event.button);    }; if (button.addEventListener) {     button.addEventListener ('mousedown', handler, false); } else {     // IE 0 1 2 3 4     buttonMap = ['???', 'Left', 'Right', '???', 'Middle'];     button.attachEvent ('onmousedown', handler); } 

La biblioteca jQuery tiene en cuenta esta característica de IE, por lo tanto, cuando la use en cualquier navegador, simplemente verifique el valor del event.which propiedad en lugar de jugar con event.button :

 $('button').mousedown(function (event) {   alert(['Left', 'Middle', 'Right'][event.which]); }); 

Pregunta número 4. Intercepción de pulsaciones de teclas en el teclado


¿Es posible interceptar, usando JavaScript, presionando las teclas de flecha (en particular, presionando las teclas Arriba y Abajo), para que, después de hacer clic en ellas, el navegador no se desplace por la página? Si esto es posible, ¿cuáles son las características de implementar esto en diferentes navegadores? Supongamos que se muestra una página en una página que no cabe completamente en la pantalla. El desplazamiento a través de las celdas de esta tabla debe organizarse con las teclas de flecha, y se requiere que el navegador no desplace la página cuando hace clic en dichas teclas.

▍ respuesta


Para implementar algo como esto, en primer lugar, debe deshabilitar la respuesta estándar del sistema para controlar las acciones. Por ejemplo, las teclas de flecha y la rueda del mouse desplazan la página, al hacer clic con el botón derecho en la página aparece un menú contextual, cuando hace clic en el botón submit , se form.submit() función form.submit() , cuando hace clic en el campo de entrada, obtiene el foco de entrada, cuando hace clic en el enlace, el navegador carga la página a la que lleva.

Esto se puede hacer de diferentes maneras . Por ejemplo, así:

 window.addEventListener("keydown", function(e) {   //  -   if([37, 38, 39, 40].indexOf(e.keyCode) > -1) {       e.preventDefault();   } }, false); 

La página siguiente normalmente no responderá a las pulsaciones de teclas de flecha.
Una cosa importante a tener en cuenta aquí. Se preventDefault() método preventDefault() antes de realizar la acción predeterminada. Por ejemplo, si hace clic en un campo para evitar que obtenga el foco de entrada, debe colgar el controlador apropiado en un evento que está en la cadena de eventos antes de la acción predeterminada. En nuestro caso, este es un evento de mousedown :

 $('input').bind ('mousedown', function (event) {   event.preventDefault();   //    return false; }); 

Cuando hace clic en el campo de entrada, se producen los siguientes eventos, en la secuencia en que se muestran aquí:

  1. mousedown
  2. focus (antes de esto, otro objeto que está perdiendo foco desencadenará un evento blur )
  3. mouseup
  4. click

Si intenta evitar que el elemento obtenga el foco de entrada, el uso de controladores de eventos para esto, comenzando con el controlador de eventos de focus , no nos ayudará.

Pregunta número 5. Detener la animación GIF y la tecla ESC


¿Cómo lidiar con el problema de detener la animación GIF al presionar la tecla ESC?

▍ respuesta


Aquí puede usar el mismo enfoque que consideramos anteriormente. En algunos navegadores, presionar la tecla ESC detiene la animación GIF y la carga de la página. Este es su comportamiento estándar, y para evitar que se comporten de esta manera, el preventDefault() evento preventDefault() es útil para nosotros, como antes. El código de la tecla ESC es 27.

Pregunta número 6. Paréntesis en IIFE


¿Cómo se utilizan los dos paréntesis cuando se declara una expresión de función invocada inmediatamente (IIFE)?

▍ respuesta


Los corchetes en esta situación le permiten al analizador comprender que hay una función frente a ellos que debe realizarse. Pero también necesita comprender qué son estos corchetes: el operador de agrupación o una construcción que indica la necesidad de llamar a la función. Por ejemplo, si usamos dos corchetes como se muestra a continuación, SyntaxError un error SyntaxError :

 function () { //  }() 

Esto se debe al hecho de que la función no tiene un nombre (debe especificar sus nombres en las declaraciones de funciones).

Intentemos reescribir este código, dando un nombre a la función:

 function foo() { //  }() 

Ahora que la función tiene un nombre, esta construcción, en teoría, debería verse bastante normal desde el punto de vista del sistema. Pero el error no desaparece, aunque ahora tiene que ver con el operador de agrupación, dentro del cual no hay expresión. Tenga en cuenta que en este caso, la instrucción de agrupación es seguida por el operador de agrupación, y no una secuencia de corchetes que le dice al sistema que se debe llamar a la función que la precede.

A menudo, IIFE está diseñado de la siguiente manera:

 (function () {   //  })() 

Pero hay otras formas, cuya esencia es indicar de alguna manera al analizador que antes es solo una expresión funcional que debe ejecutarse:

 !function () { //  }(); +function () { //  }(); [function() { //  }()]; var a = function () { //  }(); 

IIFE son ampliamente utilizados en la programación de JavaScript. Por ejemplo, esta construcción se usa en jQuery. Con su ayuda, puede crear cierres. De hecho, estamos hablando del hecho de que, usando IIFE, el programador puede ejecutar algún código en el ámbito local. Esto ayuda a proteger el alcance global de la contaminación y permite optimizar el acceso a las variables globales. Tales diseños están bien minificados.

Pregunta número 7. Pasar código en respuesta a solicitudes


El servidor, en el proceso de interacción de AJAX con el cliente, en el cuerpo de la respuesta, envía al cliente una cadena de alert ('Boom !!!'); . El cliente acepta la respuesta y ejecuta este código usando la función eval() . Como se llama Después de todo, lo que está contenido en la respuesta del servidor no es JSON, ni XML, ni HTML. ¿Qué puede decir sobre la ejecución en el cliente del código que proviene del servidor en la forma del cuerpo de la respuesta a una determinada solicitud?

▍ respuesta


De hecho, no existe un nombre especial para dicho esquema de interacción cliente-servidor. Y este es un esquema de interacción del sistema que se desaconseja encarecidamente. Esto es tan malo como almacenar código PHP en una base de datos y luego ejecutarlo usando métodos de lenguaje apropiados. Incluso si no tenemos en cuenta las consideraciones ideológicas, podemos decir que dicha arquitectura es extremadamente inflexible, por lo tanto, si el proyecto donde se usa, será necesario, a medida que se desarrolle, cambiar algo, esto no será fácil. Aquí vemos un ejemplo de mala arquitectura del sistema cuando los datos se mezclan con código y elementos de interfaz. Para cambiar algo en dicho sistema, primero debe comprender las complejidades de su intrincada arquitectura y luego, después de realizar los cambios, nuevamente "confundir" todo. No estoy hablando de reutilización de código.

Para simplificar el soporte de código, debe esforzarse por lograr la mayor separación posible de partes del sistema y reducir el número de interdependencias de estas partes. Para garantizar una conectividad débil de las partes del sistema, es decir, para asegurarse de que se pueda extraer un fragmento de la aplicación o, con la menor complejidad, reemplazarlo por otro, puede utilizar mecanismos de eventos o soluciones arquitectónicas especiales, como MVC.

Pregunta número 8. Realizar operaciones pesadas en el hilo principal


¿Cómo organizar la ejecución de ciertos comandos intensivos en recursos en JavaScript y no "suspender" todo el script?

▍ respuesta


JavaScript es un lenguaje de subproceso único. El código de las páginas web se ejecuta en el mismo hilo y se realizan transformaciones del árbol DOM. También hay temporizadores. Cada vez que realiza algunas operaciones que consumen recursos (ciclos, llamadas a funciones "pesadas"), esto conduce a una desaceleración en la interfaz de usuario o incluso a su bloqueo completo. Si las operaciones realizadas no tienen una carga particularmente grande en el sistema, su impacto en la interfaz será tan insignificante que los usuarios simplemente no lo notarán. Para hacer que la informática pesada fuera del hilo principal, el concepto de trabajadores web se introdujo en JavaScript.

Si el uso de trabajadores no es posible, entonces necesita optimizar los ciclos y las funciones "pesadas". En el libro "JavaScript. Optimización del rendimiento ”Nicholas Zakas dice que el usuario no notará nada si el flujo de la interfaz de usuario se bloquea durante 100 ms o menos.

A partir de esta idea, podemos concluir que los cálculos intensivos en recursos se pueden dividir en fragmentos, cuya implementación toma un máximo de 100 ms, después de lo cual se debe liberar el hilo principal.

Aquí hay un código de muestra del libro anterior:

 function timedProcessArray(items, process, callback) {   var todo = items.concat();   //    setTimeout(function () {       var start = +new Date();       do {           process(todo.shift());       } while (todo.length > 0 && (+new Date() - start < 50));       if (todo.length > 0){           setTimeout(arguments.callee, 25);       } else {           callback(items);       }   }, 25); } function saveDocument(id) {   var tasks = [openDocument, writeText, closeDocument, updateUI];   timedProcessArray(tasks, [id], function(){       alert("Save completed!");   }); } 

La función timedProcessArray() bloquea el hilo principal durante 25 ms, realiza una secuencia de acciones y luego lo libera durante 25 ms, después de lo cual se repite este proceso.

Pregunta número 9. Acerca del cambio de tamaño de la ventana del navegador


¿Puedo descubrir de alguna manera que el usuario ha terminado de cambiar el tamaño de la ventana del navegador?

▍ respuesta


No hay ningún evento especial que le permita averiguarlo. Pero puede averiguar si el usuario está cambiando el tamaño de la ventana utilizando el evento onresize . Este método, sin embargo, no es muy preciso.

Aquí hay un borrador de código para resolver este problema.

 var time = 0,   timerId,   TIME_ADMISSION = 100; // 0.1  function onresizeend () {   console.log('onresizeend'); }; function resizeWatcher () {   if (+new Date - time >= TIME_ADMISSION) {       onresizeend();       if (timerId) {           window.clearInterval(timerId);           timerId = null;       }   } }; $(window).resize(function () {   if (!timerId) {       timerId = window.setInterval(resizeWatcher, 25);   }   time = +new Date; }); 

Pregunta número 10. Abrir nuevas ventanas y pestañas del navegador


¿Cómo, usando el método window.open() , abrir una nueva ventana del navegador y no una nueva pestaña?

▍ respuesta


El comportamiento exacto del método window.open() depende del navegador. Opera siempre abre nuevas pestañas (aunque parecen ventanas), Safari siempre abre ventanas (aunque este comportamiento se puede cambiar). Se puede controlar el comportamiento de Chrome, Firefox e Internet Explorer.

Entonces, si window.open() pasa un parámetro adicional (posición de la ventana window.open() al método window.open() , se abrirá una nueva ventana:

 window.open('http://www.google.com', '_blank', 'toolbar=0,location=0,menubar=0'); 

Si solo se pasa un enlace a este método, se abrirá una nueva pestaña del navegador:

 window.open('http://www.google.com'); 

A menudo necesita abrir una nueva pestaña del navegador. Puede haber problemas con esto en el navegador Safari. Por defecto (depende de la configuración), el navegador, cuando se llama a window.open() , abre una nueva ventana. Pero si hace clic en el enlace, mientras presiona las teclas Ctrl + Shift/Meta + Shift , se abrirá una nueva pestaña (independientemente de la configuración). En el siguiente ejemplo, simularemos el evento de click que se genera cuando se Ctrl + Shift/Meta + Shift las Ctrl + Shift/Meta + Shift :

 function safariOpenWindowInNewTab (href) {    var event = document.createEvent ('MouseEvents'),        mac = (navigator.userAgent.indexOf ('Macintosh')> = 0); //  Ctrl + Shift + LeftClick / Meta + Shift + LeftClick ()    //       event.initMouseEvent (        / * type * / "click",        / * canBubble * / true        / * cancelable * / true,        / * view * / window,        / * detail * / 0,        / * screenX, screenY, clientX, clientY * / 0, 0, 0, 0,        / * ctrlKey * /! mac,        / * altKey * / false,        / * shiftKey * / true        / * metaKey * / mac,        / * button * / 0,        / * relatedTarget * / null    ); //     ,   ,         $ ('<a/>', {'href': href, 'target': '_blank'}) [0] .dispatchEvent (event); } 

Pregunta No. 11. Copia profunda de objetos


¿Cómo organizar efectivamente la copia profunda de objetos?

▍ respuesta


Si el objeto cuya copia desea crear (llamémoslo oldObject ) no cambia, será más efectivo hacerlo a través de su prototipo (esto se hace muy rápidamente):

 function object(o) {   function F() {}   F.prototype = o;   return new F(); } var newObject = object(oldObject); 

Si realmente necesita realizar la operación de clonar un objeto, entonces la forma más rápida será recurrentemente, optimizando este proceso, pasando por sus propiedades. Quizás este es el algoritmo más rápido para crear copias profundas de objetos:

 var cloner = {   _clone: function _clone(obj) {       if (obj instanceof Array) {           var out = [];           for (var i = 0, len = obj.length; i < len; i++) {               var value = obj[i];               out[i] = (value !== null && typeof value === "object") ? _clone(value) : value;           }       } else {           var out = {};           for (var key in obj) {               if (obj.hasOwnProperty(key)) {                   var value = obj[key];                   out[key] = (value !== null && typeof value === "object") ? _clone(value) : value;               }           }       }       return out;   }, clone: function(it) {       return this._clone({       it: it       }).it;   } }; var newObject = cloner.clone(oldObject); 

Si usa jQuery, puede recurrir a las siguientes construcciones:

 //   var newObject = jQuery.extend ({}, oldObject); //   var newObject = jQuery.extend (true, {}, oldObject); 

Pregunta número 12. Destructores de JavaScript


¿Cómo crear algo como un destructor en JavaScript? ¿Cómo gestionar el ciclo de vida de los objetos?

▍ respuesta


En JavaScript, un objeto se eliminará de la memoria después de que desaparezca la última referencia:

 var a = {z: 'z'}; var b = a; var c = a; delete az; delete a; //    a console.log (b, c); // ,  ,    

Usar algo como un "destructor" en JavaScript solo da como resultado la eliminación del contenido del objeto, pero no lo elimina de la memoria.

Pregunta número 13. Procesamiento de datos binarios


¿Es posible procesar datos binarios en JavaScript? Y si es así, ¿cómo?

▍ respuesta


Si necesita trabajar con datos binarios en una aplicación de JavaScript, puede intentar usar la biblioteca Binary Parser . Pero su código es el infierno. En ES6 +, hay una sugerencia con respecto al tipo StructType (esto es lo mismo que está representado en C ++ por el tipo de datos compuesto de struct ). Este tipo de datos es necesario para simplificar el trabajo con datos binarios. Trabajar con él podría verse más o menos así:

 const Point2D = new StructType({ x: uint32, y: uint32 }); const Color = new StructType({ r: uint8, g: uint8, b: uint8 }); const Pixel = new StructType({ point: Point2D, color: Color }); const Triangle = new ArrayType(Pixel, 3); let t = new Triangle([{ point: { x:  0, y: 0 }, color: { r: 255, g: 255, b: 255 } },                     { point: { x: 5, y: 5 }, color: { r: 128, g: 0,   b: 0 } },                     { point: { x: 10, y: 0 }, color: { r: 0,   g: 0, b: 128 } }]); 

Pregunta número 14. Cambio de variables en una función de otra función


¿Cómo cambiar las variables ubicadas en una función de otra función?

▍ respuesta


Aquí puede aplicar varios enfoques:

  1. Puede usar el enlace al contexto de la función que nos interesa (la función primer() en el siguiente ejemplo) en la función smth() .
  2. Puede pasar una función creada en el contexto de la función primer() a la función smth() .

     var primer = function () {    var a, b, c, d, e = {}; smth (function () {        a = 1;        b = 2;        c = 3;        d = 4;    }, e); alert ([a, b, c, d, e.pewpew]); }, smth = function (callback, e) {    callback ();    e.pewpew = "pewpew"; }; primer (); 
  3. Anteriormente (antes de Firefox 3.6), podía acceder al contexto utilizando la propiedad __parent__ , pero ya en Firefox 4 esta característica se eliminó.

Pregunta número 15. Trabajar con funciones


Cuéntanos cómo se pueden llamar las funciones en JavaScript.

▍ respuesta


Supongo que no es necesario hablar sobre cómo llamar a funciones, métodos y constructores durante el trabajo normal con ellos. Hablemos sobre cómo usar los métodos call() y apply() .

Usando call () para configurar el constructor de un objeto


 //   function extend (newObj, oldObj) {   function F () {};   F.prototype = oldObj.prototype;   newObj.prototype = new F ();   return newObj }; var Obj = function () {   this.obj_var = 100; }; Obj.prototype.obj_proto_var = 101; var NewObj = function () {   Obj.call (this); //   Obj     obj_var   this.new_obj_var = 102; }; extend (NewObj, Obj) NewObj.prototype.new_obj_proto_var = 103; new NewObj (); // {new_obj_proto_var: 103, new_obj_var: 102, obj_proto_var: 101, obj_var: 100} 

Convierta objetos tipo matriz en matrices


Los objetos tipo matriz son similares a las matrices JavaScript, pero no lo son. En particular, esto se expresa en el hecho de que tales objetos no tienen métodos de matrices ordinarias. Entre tales objetos, por ejemplo, se pueden observar los arguments objeto de las funciones tradicionales y los resultados del método getElementsByTagName () .

 // document.getElementsByTagName ("div")  ,   ,    , ,  ,        document.getElementsByTagName ("div"). forEach (function (elem) {    // ... }); // TypeError: document.getElementsByTagName ("div"). forEach is not a function //    Array.prototype.slice.call(document.getElementsByTagName("div")).forEach (function (elem) {   // OK }); //        console.log(Array.prototype.slice.call ('pewpew')) // ["p", "e", "w", "p", "e", "w"] //  IE8    

Crear objetos de envoltura


Esta técnica de usar call() y apply() permite crear objetos wrapper. , - foo() , bar() .

:

 function bar () {console.log(arguments)} // foo (context, arg1, arg2, ...) function foo () {    var context = arguments [0];    var args = Array.prototype.slice.call (arguments, 1); //     bar    bar.apply (context, args); } 

Function.call.apply() :

 function foo() {   Function.call.apply(bar, arguments); } 

, Function.call.apply() , , foo() , bar .

№16.


, , ?


. , Firefox 3.6, __parent__ , .

№17.


, , , eval() ?


, . , :

 // 1:  eval() (function () {    "use strict";    var globalObject = (0, eval) ("this"); //  :)    return globalObject; } ()); // 2:    (function (global) {    // ... } (window)); // 3:      (function () {    return this; } ()); // 4:            ,       . //  -    "use strict"; (function (global) {    // global }) (this); 

№18.


, JavaScript, , ?


JavaScript - « ». . . , :

 $('#smth').click(function onSmthClick(event) {   if (smth) {       //         event.handlerFunction = onSmthClick;       event.handlerContext = this;       //         //  otherObjectSetSomeEvent   event.handlerFunction          otherObjectSetSomeEvent(event);   } else {       //  -    } }); 

— , . , 2 :

 $('#smth'). click (function handler1 (event) {   if (smth) {       //         leftObjectSetSomeEvent(event, function handler2 (e) {           //  -   e       });   } else {       //  -    } }); function leftObjectSetSomeEvent(event, callback) {   callback (event);   //    } 

№19.


JavaScript ? — , .


click «» DOM. (, , ).

 // jQuery $(window).bind ('click', function (e) {   console.log ('Clicked on', e.target); }); //       $('#pewpew').delegate ('*', 'click', function(e) {   console.log('Clicked on', e.target); }); //     $('#pewpew').delegate('.pewpew', 'click', function (e) {   console.log ('Clicked on element with .pewpew class name'); }); 

№20. XHR-


XHR- jQuery?


, - :

 function xhr(m, u, c, x) { with(new XMLHttpRequest) onreadystatechange = function (x) {   readyState ^ 4 || c(x.target) }, open(m, u), send() } 

- :

 function xhr(m, u, c, x) { with(new(this.XMLHttpRequest || ActiveXObject)("Microsoft.XMLHTTP")) onreadystatechange = function (x) {   readyState ^ 4 || c(x) }, open(m, u), send() } 

:

 xhr('get', '//google.com/favicon.ico', function (xhr) { console.dir(xhr) }); 

№21. -


(reflow) (repaint) -?


  1. requestAnimationFrame() , , setInterval() setTimeout() . , , , , , . , JavaScript- CSS- SVG-. , , , , , , . , , .
  2. float- ( ).
  3. DOM. , , , DOM ( ).
  4. — . ( , , ). Aquí hay un ejemplo:

     //      element.style.left = "150px;"; // ... element.style.color = "green"; //  ,   ,    element.setAttribute ('style', 'color: green; left: 150px'); 
  5. ( ).
  6. — ( style.display = "none" ). , .

, -, . , , , , .

  1. .
  2. DOM- ( — ).
  3. Document.querySelectorAll() firstElementChild .
  4. , document.getElementsByTagName() ( , DOM, ).

№22. Node.js


Node.js, , ?


, ( PHP Apache). , , . Node.js — . , , cluster . (master) - (worker). , .

№23. runInNewContext() Node.js


runInNewContext() Node.js.


. , ( Node.js- Nodester). - , runInNewContext() . , «», . «» , , runInNewContext() .

Resumen


JavaScript . , - , .

Estimados lectores! , - , , JavaScript , ?

Source: https://habr.com/ru/post/es436454/


All Articles