La pregunta de JavaScript más completa (incluidas las respuestas)

1. La diferencia entre llamar, aplicar y vincular

Estos tres se utilizan para definir el contexto. call y apply especificarán el contexto y ejecutarán la función; bind establecerá el contexto de por vida pero no ejecutará la función y devolverá una nueva función. Las formas de los parámetros pasados ​​en call y apply son diferentes. Call es una lista separada con comas que separan los parámetros; apply es una matriz. function.call(objeto de contexto, parámetros, parámetros, parámetros);function.apply(objeto de contexto, [parámetros, parámetros, parámetros]);

var obj = { 
 a: 10 
} 
​función
fun(b, c){ 
 console.log(this.a + b + c); 
} 
​fun.call
(obj, 3, 4); 
fun.apply(obj, [ 3, 4]); 
fun = fun.bind(obj); // Devuelve la nueva función 
fun(3,4);


2. ¿Cuáles son los tipos de datos?

Tipos básicos: número, cadena, booleano, indefinido, nulo, símbolo

Tipos de referencia: matriz de matriz, función de función, objeto de objeto


3. Cómo detectar el tipo de datos

typeof puede detectar: ​​números, cadenas, booleanos, indefinidos, símbolos, funciones

instancia de puede detectar: ​​matriz

Método universal Object.prototype.toString.call()


4. La diferencia entre cada afirmación

4.1. La diferencia entre para y para...en y para...de

for loop, recorre toda la matriz

for...in fortalece el bucle, no solo puede atravesar matrices, sino también atravesar objetos y métodos en sus prototipos.

para...de atraviesa matrices y objetos enumerables

4.2 La diferencia entre cambiar y si

El interruptor se utiliza para determinar el valor preciso.

si se utiliza para determinar el rango de valores

4.3 La diferencia entre while y do... while

while se ejecuta cuando se cumplen las condiciones

do... while se ejecuta primero una vez y luego se juzga si cumple con las condiciones y debe ejecutarse una vez más que while.

4.4 La diferencia entre romper y continuar

break es saltar fuera del bucle actual y terminar el bucle

continuar es saltar del bucle actual y ejecutar el siguiente bucle


5. Cierre

El cierre significa que la función puede recordar el alcance cuando se definió originalmente. No importa dónde se ejecute la función, siempre puede recordar ese alcance y cubrir las variables en el nuevo alcance. Contenedor de estado predecible; implementar modularización, realizar encapsulación privada de variables; puede implementar iteradores. Desventajas de los cierres: 1. Los cierres tienen un problema muy grave, que es el problema del desperdicio de memoria. Este desperdicio de memoria no se debe solo a que reside en la memoria, sino que, lo que es más importante, el uso inadecuado de los cierres provocará la generación de memoria no válida. 2. Problemas de rendimiento Cuando se utilizan cierres, se implicará el acceso entre alcances y cada acceso provocará una pérdida de rendimiento. Entonces, en los scripts, es mejor tener cuidado al usar cierres, que tienen problemas tanto de memoria como de velocidad. Sin embargo, podemos reducir el impacto en la velocidad de ejecución almacenando variables de alcance cruzado en variables locales y luego accediendo a las variables locales directamente.

      función foo(){ 
        var a = 0; 
        función f(){ 
          a++; 
          devolver a; 
        } 
        devolver f; 
      } 
      var res = foo(); 
      res(); 
      res(); 
      res(); 
      console.log(res( )); // 4 el valor de a se almacena en la memoria y no se liberará


6. Prototipo y cadena de prototipos.

Prototipo: cada tipo de objeto tiene un prototipo implícito __ proto __, y cada función tiene un prototipo explícito, que apunta a su objeto prototipo.

Cadena de prototipo: El prototipo de un objeto tiene su propio prototipo, hasta que el prototipo de un objeto es nulo, formando el último eslabón de esta cadena, esta cadena nivel por nivel es la cadena de prototipo.


7. Herencia

7.1 Herencia de la cadena de prototipos

/** 
 * Desventaja: los atributos de tipo de referencia son compartidos por todas las instancias, 
 * Al crear una instancia de Child, los parámetros no se pueden pasar a Person 
 */ 
   function Person() { 
    this.name = "xiaopao"; 
   } 
   Person.prototype.getName = función () { 
    consola.log(este.nombre); 
   }; 
   función Niño() {} 
   Niño.prototipo = nueva Persona();

7.2 Herencia del constructor prestado (herencia clásica)

/* 
Ventajas: 
1. Evita que los atributos de tipo de referencia sean compartidos por todas las instancias 
2. Los parámetros se pueden pasar a Parent in Child 
Desventajas: 
1. Solo instancias de subclases, no instancias de clases principales 
2. Los métodos se definen en el constructor, un método se creará cada vez que se cree una instancia 
*/ 
   function Child() { 
    Person.call(this); 
   }

7.3 Herencia combinada

/* 
Ventajas: combina las ventajas de la herencia de cadena de prototipos y los constructores, es el patrón de herencia más utilizado en JavaScript. 
Desventajas: el constructor de la clase principal se llama dos veces. 
El mayor problema con la herencia combinada es que no importa las circunstancias, el El constructor de supertipo se llamará dos veces. Función: una vez al crear el 
prototipo de subtipo y otra vez dentro del constructor de subtipo) 
*/ 
   function Child(nombre, edad) { 
    Parent.call(this, nombre); // Segunda llamada a Parent( ) 
    this.age = edad; 
   } 
   Child.prototype = new Parent(); // Primera llamada a Parent()

7.4 Herencia prototípica

// Desventajas: los valores de propiedad que contienen tipos de referencia siempre compartirán los valores correspondientes, que es lo mismo que 
   la función de herencia de cadena de prototipo CreateObj(o) { 
    function F() {} 
    F.prototype = o; 
    return new F(); 
   } 
   var persona = { 
    nombre: "xiaopao", 
    amigo: ["daisy", "kelly"], 
   }; 
   var persona1 = CreateObj(persona);

7.5 La herencia parasitaria puede entenderse como la adición de algunas funciones o atributos sobre la base de una herencia prototípica.

// Desventajas: al igual que pedir prestado un constructor, el método se creará cada vez que se cree un objeto 
var
   ob = { 
    name: "xiaopao", 
    friends: ["lulu", "huahua"], 
   }; 
​function
   CreateObj( original){ 
    var clone = Object.create(original); //Crea un nuevo objeto llamando a una 
    función clone.sayHi = function(){ //Mejora este objeto de alguna manera 
        alert("Hi"); 
    }; 
    return clone ; // Devolver este objeto 
   } 
//
   La función CreateObj anterior tiene un nuevo método de escritura estándar en ECMAScript5. El efecto de Object.create(ob) es el mismo. Consulte el siguiente código var 
   ob1 = CreateObj(ob); 
   console.log (ob1.nombre); // xiaopao

7.6 Herencia combinada parasitaria

// Ventajas: herencia perfecta 
// Desventajas: mucho código, muy problemático de usar 
        function Parent(name) { 
            this.name = name; 
        } 
​Parent.prototype.sayName
        = function () { 
            console.log(this.name) ; 
        }; 
​función
        Niño(nombre) { 
            Parent.call(este, nombre); 
        } 
​función
        CreateObj(o) { 
            función F() { } 
            F.prototype = o; 
            devolver nuevo F(); 
        } 
función
        prototipo( hijo, padre) { 
            var prototipo = CreateObj(padre.prototipo); 
            prototipo.constructor = hijo;
            niño.prototipo = prototipo; 
        } 
        prototipo(Niño, Padre); 
​​var

        niño = new Niño("大圣"); 
        niño.decirNombre(); 
        console.log(niño);

7.7, herencia es6

clase Niño extiende Padre {}


8. Recursividad y optimización recursiva.

La recursividad es cuando una función se llama a sí misma. Pero no puede llamarse a sí mismo infinitamente, es necesario que haya una salida, de lo contrario se convertirá en un bucle infinito. Las llamadas a funciones se implementan a través de la estructura de datos de la pila. Cada vez que se ingresa una llamada a una función, se agrega una capa de marcos de pila a la pila. Cada vez que una función regresa, se resta una capa de marcos de pila de la pila. Dado que el tamaño de la pila no es infinito, demasiadas llamadas recursivas provocarán un desbordamiento de la pila.

// Bucle para encontrar la suma de todos los números 1-5 
var sum = 0; 
for(var i = 1; i <= 5; i++){ 
    sum += i; 
} 
console.log(sum) // 15 
​/ /
Implementar recursivamente la 
función de suma sum(n){ 
    if(n === 1){ 
        return 1; 
    } 
    return n + sum(n-1); 
} 
console.log(sum(5)); //15

La optimización de la recursión de cola es una forma de resolver el desbordamiento de la pila de llamadas recursivas. La recursividad de cola significa que cuando la función regresa, se llama a sí misma y la declaración de retorno no puede contener expresiones. De esta manera, el compilador o intérprete puede optimizar la recursividad de cola para que, sin importar cuántas veces se llame a la recursividad, solo ocupe un marco de pila y no se produzca ningún desbordamiento de pila.

// El ejemplo anterior realiza de forma recursiva 
la función de optimización de recursión de cola sum(n, m = 0){ 
    if(n === 1){ 
        return 1 + m; 
    } 
    return sum(n-1, n + m); 
} 
console. log (suma(5)); //15 
​//
O while 
función de optimización suma(n, m = 0){ 
    while(n >= 1){ 
        return suma(n - 1, n + m); 
    } 
    return m ; 
} 
consola.log(suma(5)); // 
15


9. Principio de funcionamiento y empaquetado de Ajax.

1. Cree un objeto XMLHttpRequest. 2. Establezca el método de solicitud. open() 3. Llame a la función de devolución de llamada. onreadystatechange 4. Enviar solicitud. enviar()

     function ajax(opciones) { 
        const { tipo, tipo de datos, datos, tiempo de espera, url, éxito, error } = opciones; 
        var params = formatParams(data); 
        var xhr; 
        //Considere la compatibilidad 
        if (window.XMLHttpRequest) { 
          xhr = new XMLHttpRequest(); 
        } else if (window.ActiveObject) { 
          //Compatible con versiones inferiores a IE6 
          xhr = new ActiveXobject("Microsoft.XMLHTTP"); 
        } 
        //Iniciar y enviar una solicitud 
        if (type == "GET") { 
          xhr.open("GET", url + "?" + params, true); 
          xhr.send(); 
        } else if (tipo == "POST") { 
          xhr.open("post", url,true); true); 
          //Establece el tipo de contenido al enviar el formulario
          //Formato de solicitud de datos de tipo de contenidoestado;  
          if (xhr.readyState == 4) {
            estado var = xhr.status; 
            if ((estado >= 200 && estado < 300) || estado == 304) { 
              éxito && éxito(xhr.responseText, xhr.responseXML); 
            } else { 
              error && error(estado); 
            } 
          } 
        }; 
      } 
​//
      格式化请求参数
      function formatParams(data) { 
        var arr = []; 
        for (var nombre en datos) { 
          arr.push( 
            encodeURIComponent(nombre) + "=" + encodeURIComponent(datos[nombre]) 
          ); 
        } 
        arr.push(("v=" + Math.random()).replace(".", "")); 
        devolver arr.join("&");
      }


10. Dominio cruzado

Dominio cruzado se refiere a un documento o script en un dominio que intenta solicitar recursos en otro dominio. El dominio cruzado aquí es amplio. De hecho, lo que generalmente llamamos dominio cruzado es en un sentido estricto y es un tipo de escenario de solicitud restringido por la política del mismo origen del navegador. Política de mismo origen SOP (Política de mismo origen) es una convención introducida en el navegador por Netscape en 1995. Es la función de seguridad principal y más básica del navegador. Si falta la misma política de origen, el navegador será vulnerable a XSS, CSFR y otros ataques. El llamado mismo origen significa que "protocolo + nombre de dominio + puerto" son iguales. Incluso si dos nombres de dominio diferentes apuntan a la misma dirección IP, no son del mismo origen.

Método 1: compartir recursos entre dominios CORS entre dominios significa que el servidor agrega "AccessControll-Allow-Origin: *" al encabezado de retorno HTTP. Los tipos de solicitud "Access-Controll-Allow-METHODS: GET, POST" DELETE y PATCH emitirán solicitudes de verificación previa de OPCIONES.

Método 2: Proxy entre dominios, elemento de configuración de proxy en webpack-dev-server. ProxyTable en configuración

Método 3: JSONP, aprovechando la vulnerabilidad de que el srcipt de la página no tiene restricciones entre dominios, introdúzcalo con el src del script y luego defina la función de devolución de llamada en la página, $.ajax({dataType: 'jsonp '}) en jQuery.

Método 4: iframe entre dominios, usado junto con window.name o location.hash o document.domain

Método 5: la interfaz de proxy inverso de nginx cruza dominios. Configure un servidor proxy a través de nginx (el nombre de dominio es el mismo que el dominio1, pero el puerto es diferente) como trampolín. El proxy inverso accede a la interfaz del dominio2 y también puede modificar el información de dominio en la cookie para facilitar la cookie de dominio actual. Escriba para lograr el inicio de sesión entre dominios.

Método 6: dominio cruzado ajax de jquery, tipo de datos: 'jsonp'


11. Flujo de eventos y delegación de eventos

El flujo de eventos generalmente se divide en tres etapas: 1. Etapa de captura (de afuera hacia adentro) 2. Etapa de destino (etapa de ejecución) 3. Etapa de burbujeo (de adentro hacia afuera)

Prevenir la propagación de eventos e.stopPropagation() Prevenir la acción predeterminada e.preventDefault()

Delegación de eventos: consiste en delegar eventos al padre, utilizar la distribución de eventos y especificar solo un controlador de eventos para administrar todos los eventos de un determinado tipo.


12. Bucle de eventos

Las tareas sincrónicas ingresan al hilo principal y las tareas asincrónicas ingresan a la tabla de eventos y registran una función. Cuando se completa lo especificado, la tabla de eventos moverá esta función a la cola de eventos. Cuando las tareas en el hilo principal están vacías después de la ejecución, la función correspondiente se leerá de la cola de eventos y se ejecutará en el hilo principal. El proceso anterior se repetirá continuamente, lo que a menudo se denomina bucle de eventos.

      console.log("inicio del script"); 
​setTimeout
      (function () { 
        console.log("setTimeout"); 
      }, 0); 
​Promise.resolve
      () 
        .then(function () { 
          console.log("promise1 "); 
        }) 
        .then(function () { 
          console.log("promise2"); 
        }); 
​console.log
      ("fin del script"); 
      /* El resultado de la ejecución es: inicio del script, fin del script, promesa1, promesa2, setTimeout Debido a que Promise es una microtarea, el hilo principal primero borrará la cola de microtarea después de que se complete la tarea de sincronización y luego ejecutará la cola de macrotarea*/

Las microtareas son iniciadas por el propio JavaScript, que incluyen: Process.nextTick, Promesa, MutationObserver

Las tareas macro las inician los hosts, como navegadores y nodos. Incluye: setTimeout, setInterval, setImmediate, postMessage


13. Antivibración y estrangulamiento

// Acelerador: borra el temporizador dentro del temporizador y ejecuta eventos rítmicamente 
        function throttle(callback, delay = 1000){ 
            let timer = null; 
            function f(){ 
                if(!timer){ 
                    timer = setTimeout(() => { 
                        callback && callback.call(this); 
                        clearTimeout(timer); 
                        timer = null; 
                    }, delay); 
                } 
            } 
            return f; 
        } 
      
// Anti-vibración: borre el temporizador delante del temporizador y solo ejecute el último evento, puede extender el tiempo de ejecución indefinidamente 
        function debounce(callback, delay = 1000) {  
            let timer = null; 
            function f() {
                clearTimeout(timer); 
                timer = setTimeout(() => {
                    devolución de llamada && devolución de llamada.call(this); 
                }, demora); 
            } 
            devolver f; 
        }


14. Clonación profunda y clonación superficial

Clon superficial: mismo valor y misma dirección. Copia superficial significa que el objeto de origen y el objeto de copia comparten una entidad, solo las variables a las que se hace referencia son diferentes (nombres diferentes). Los cambios en cualquier objeto afectarán al otro objeto. Por ejemplo: Object.assign; = asignación de signo igual; intercepción de corte.

Clonación profunda: mismo valor pero dirección diferente. Copia profunda significa que el objeto de origen y el objeto copiado son independientes entre sí y los cambios en cualquier objeto no afectarán al otro. Tales como: JSON.parse(JSON.stringify());

      function deepClone(target) { 
        // Definir una variable 
        let result; 
        // Si lo que necesita copiarse en profundidad es un objeto, 
        if (typeof target === "object") { 
          // Si es una matriz, 
          if (Array .isArray (destino)) { 
            resultado = []; // Asigna el resultado a una matriz y realiza un recorrido 
            for (let i in target) { 
              // Clona recursivamente cada elemento de la matriz 
              result.push(deepClone(target[i]) ); 
            } 
            // Determina si el valor actual es nulo; asigna el valor directamente a nulo 
          } else if (target === null) { 
            result = null; 
            // Determina si el valor actual es un objeto RegExp, asigna el valor directamente  
          } else if (target.constructor === RegExp) { 
            resultado = target;
          } else { 
            // De lo contrario, es un objeto ordinario, directamente en el bucle, asigna recursivamente todos los valores del objeto
            resultado = {}; 
            for (let i in target) { 
              result[i] = deepClone(target[i]); 
            } 
          } 
          // Si no es un objeto, es un tipo de datos básico, entonces asigna el valor directamente 
        } else { 
          resultado = objetivo; 
        } 
        // Devuelve el resultado final 
        devuelve resultado; 
      }


15. La diferencia entre cookie, sessionStorage y localStorage

15.1. Los datos de las cookies siempre se transportan en la solicitud http desde la misma fuente (incluso si no son necesarios), es decir, la cookie se pasa de un lado a otro entre el navegador y el servidor, pero sessionStorage y localStorage no envían automáticamente el datos al servidor y sólo se guardan localmente. Los datos de las cookies también tienen el concepto de ruta (ruta), que puede limitar las cookies para que solo pertenezcan a una determinada ruta. 15.2. El límite de tamaño de almacenamiento también es diferente. Los datos de las cookies no pueden exceder los 4K. Al mismo tiempo, porque cada solicitud http lleva Cookies, las cookies solo son adecuadas para guardar una pequeña cantidad de datos, datos pequeños como el ID de sesión. Aunque sessionStorage y localStorage también tienen limitaciones de tamaño de almacenamiento, son mucho más grandes que las cookies y pueden alcanzar 5 M o más. 15.3. El período de validez de los datos es diferente. sessionStorage: solo válido hasta que se cierre la ventana actual del navegador; localStorage: siempre válido, ventana o navegador Siempre se guarda cuando se cierra, por lo que se utiliza como datos persistentes; cookie: solo es válida antes del tiempo de vencimiento de la cookie establecido, incluso si la ventana está cerrada o el navegador está cerrado. 15.4 Diferentes alcances, sessionStorage no se comparte en diferentes ventanas del navegador, ni siquiera en la misma página; el almacenamiento local se comparte en todas las ventanas homólogas; las cookies también se comparten en todas las ventanas homólogas. 15.5. El almacenamiento web admite el mecanismo de notificación de eventos, que puede enviar notificaciones de actualización de datos a los oyentes. 15.6 La interfaz API de almacenamiento web es más cómoda de usar


16. La diferencia entre solicitudes de obtención y publicación

GET es inofensivo cuando el navegador retrocede, mientras que POST envía la solicitud nuevamente.

La dirección URL generada por GET se puede marcar como favorita, pero POST no.

El navegador almacenará activamente en caché las solicitudes GET, pero no POST, a menos que se configuren manualmente.

Las solicitudes GET solo pueden codificarse en URL, mientras que POST admite múltiples métodos de codificación.

Los parámetros de solicitud GET se conservarán por completo en el historial del navegador, mientras que los parámetros en POST no se conservarán.

Existe un límite de longitud para los parámetros transmitidos en la URL de la solicitud GET, pero no hay límite para la longitud de la solicitud POST.

En cuanto al tipo de datos de los parámetros, GET sólo acepta caracteres ASCII, mientras que POST no tiene restricciones.

GET es menos seguro que POST porque los parámetros se exponen directamente en la URL, por lo que no se puede utilizar para pasar información confidencial.

Los parámetros GET se pasan a través de la URL y la POST se coloca en el cuerpo de la solicitud.


17. ¿Qué hace el nuevo operador?

El objeto Object no se crea explícitamente en el constructor, de hecho, se crea automáticamente un objeto vacío en segundo plano y se asignan atributos y métodos directamente a este objeto, lo que apunta al objeto creado. No hay valor de retorno, el objeto se devuelve automáticamente en segundo plano y el objeto hereda el prototipo del constructor.

// Simular la implementación del constructor 
 var Book = function(name) { 
   this.name = name; 
 }; 
 // Uso normal 
 var js = new Book('js'); 
 // Usar simulación de código para probar en navegadores que no sean IE, IE el navegador no admite 
 var javascript = {}; 
 javascript.__proto__ = Book.prototype; 
 Book.call(javascript, 'js');


18. Ataques XSS y ataques CSRF

XSS: ataques de scripts entre sitios Script entre sitios. Debido a que es fácil malinterpretarlo cuando se llama css, se cambió a xss. Por ejemplo, datos JSON:

      var obj = [ 
        { 
          id: 1, 
          nombre: "<script>alert('jajaja')</script>", 
          edad: 12, 
        } 
      ];

El código de script aparece donde no debería, lo que provoca algunos peligros potenciales. Las vulnerabilidades XSS permiten a las personas insertar una declaración funcional en una página web. XSS significa "cross-site scripting" y es un tipo de ataque de inyección. Su característica es que no causa ningún daño al lado del servidor, pero utiliza algunos métodos normales de interacción en el sitio, como publicar comentarios y enviar contenido que contenga JavaScript. En este momento, si el servidor no filtra ni escapa estos scripts y los publica como contenido en la página, otros usuarios ejecutarán estos scripts cuando visiten esta página. Prevención: ① Utilice expresiones regulares para evitar que los usuarios envíen declaraciones que contengan palabras peligrosas como <, eval, script, etc. ② Al mostrar, no utilice directamente insideHTML, sino use internalText o escape <.

El nombre completo de CSRF es "falsificación de solicitudes entre sitios" y el nombre completo de XSS es "secuencias de comandos entre sitios". Se parecen un poco. Ambos son ataques entre sitios: no atacan al servidor sino a los usuarios que normalmente visitan el sitio web. Pero como se mencionó anteriormente, sus tipos de ataque se clasifican en diferentes dimensiones. Como sugiere el nombre, CSRF es una solicitud falsificada que pretende ser la operación normal de un usuario en el sitio. Sabemos que la gran mayoría de los sitios web utilizan cookies y otros métodos para identificar a los usuarios (incluidos los sitios web que utilizan la sesión del lado del servidor, porque los ID de sesión se almacenan principalmente en cookies) y luego los autorizan. Por lo tanto, la mejor manera de falsificar el funcionamiento normal del usuario es utilizar XSS o suplantación de enlaces para permitir que el usuario inicie una solicitud que el usuario no conoce en la máquina local (es decir, el navegador con la cookie de identidad). Es decir, si el usuario no escribe el nombre honestamente y escribe <script> uno por uno, se llama XSS. Si va más allá y escribe $.post() y envía document.cookie, será CSRF. Solución: ① Utilice la verificación de token para verificar la dirección IP del usuario para generar el código MD5, un método de verificación más seguro ② Evite XSS.


19. Mecanismo de recolección de basura

En términos generales, los objetos a los que no se hace referencia son basura y deben borrarse. Hay una excepción. Si varias referencias de objetos forman un anillo y se refieren entre sí, pero no se puede acceder a ellos en absoluto, estos objetos también son basura y deben borrarse. . Hay dos métodos principales de recolección de basura: uno es el borrado de marcas, lo que significa que las variables después de su uso se asignan a nulo, y el otro es el recuento de referencias, que cuenta la referencia de los objetos usados ​​y los recicla si es 0.


20. Operaciones DOM comunes

crear elemento crear

Agregar al final de appendChild

insertar antes insertar antes

cloneNode(verdadero) clon

eliminarNiño() eliminar

parentNodenodo padre

childNodes // todos los nodos secundarios

firstChild // primer nodo hijo

lastChild //El último nodo hijo

anteriorElementSibling// Nodo hermano anterior

nextElementSibling//Siguiente nodo hermano

Nombre del usuario: document.getElementById() 、document.getElementsByTagName() 、document.getElementsByClassName() 、document.getElementsByName() 、document.querySelector() 、document.querySelectorAll()


21. La diferencia entre AMD, CMD, ES6 y CommonJS

CommonJS: referencia del módulo (requerir) salida del módulo (exportaciones) identificación del módulo (módulo) ES6: referencia del módulo (importar) salida del módulo (exportar) El primero admite la importación dinámica, es decir, require(${path}/xx.js), y este último no es compatible actualmente. La primera es una importación sincrónica. Debido a que se usa en el lado del servidor y todos los archivos son locales, la importación sincrónica tendrá poco impacto incluso si el hilo principal está bloqueado. Esta última es una importación asincrónica, porque se usa en un navegador y requiere la descarga de archivos. Si también se usa la importación sincrónica, tendrá un gran impacto en la renderización. El primero es una copia del valor al exportar, incluso si el valor exportado cambia, el valor importado no cambiará, por lo que si desea actualizar el valor, debe volver a importarlo. Sin embargo, este último utiliza enlace en tiempo real. Los valores importados y exportados apuntan a la misma dirección de memoria, por lo que el valor importado cambiará con el valor exportado. Tanto AMD como CMD usan define para definir el módulo y requieren para introducir el módulo. La diferencia es que AMD es una dependencia previa. CMD es una dependencia cercana

      // Las dependencias de AMD deben declararse al principio 
      define(["./a", "./b"], function (require, factory) { 
        // hacer algo... 
      }); 
​//
      CMD   
      define(function ( require, factory) { 
        var a = require('./a'); // Las dependencias están escritas cerca 
        // haz algo... 
      });

Supongo que te gusta

Origin blog.csdn.net/xiaozgm/article/details/125750137
Recomendado
Clasificación