Cómo importar/exportar una clase en Vanilla JavaScript (JS)

10 minutos de lectura

Avatar de usuario de RBT
RBT

Estoy usando Vanilla JavaScript (JS). Ahora, estoy tratando de aprovechar el concepto de importación/exportación clase y módulo que vino como parte del lanzamiento de ECMA-2015 (ECMA-6).

Por favor, vea el fragmento de código a continuación:

rectángulo.js:

export default class  Rectangle{
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

myHifiRectangle.js:

import Rectangle from 'rectangle.js';

class MyHiFiRectangle extends Rectangle {
  constructor(height, width) {
      super(height,width);
      this.foo= "bar";  
 }
}

Estoy tratando de referirme a los archivos JS mencionados anteriormente en una página HTML llamada prueba.html Como se muestra abajo:

<!DOCTYPE html>
<html lang = "en">
   <head>
      <meta charset = "UTF-8">
      <title>Javascipt by Rasik Bihari Tiwari</title>
       <script src="https://stackoverflow.com/questions/44490627/Scripts/rectangle.js"></script>
       <script src="Scripts/myHiFiRectangle.js"></script>
      <script type="text/javascript">
    
   var v = new MyHiFiRectangle(2,4);
   console.debug(v.foo);
      </script>
   </head>
   <body >

   </body>

</html>

Entonces, traté de cargar prueba.html en el navegador. El resultado es diferente en diferentes navegadores.

En Google Chrome obtengo el siguiente error:

SyntaxError no detectado: exportación de token inesperada

En Mozilla firefox obtengo el siguiente error:

SyntaxError: las declaraciones de exportación solo pueden aparecer en el nivel superior de un módulo

SyntaxError: las declaraciones de importación solo pueden aparecer en el nivel superior de un módulo

ReferenceError: MyHiFiRectangle no está definido[Learn More]

Intenté reordenar los archivos JS a los que se hace referencia en el cabeza etiqueta del archivo HTML pero no tuvo ningún impacto.

Nota: Para ser claro nuevamente, no estoy usando transpiladores como Babel. Estoy tratando de verificar el soporte nativo de exportación/importación clase y módulo construye en Vanilla JS y cómo funciona.

  • He publicado una respuesta a su pregunta.

    – curioso.netter

    16 de enero de 2019 a las 22:23

  • Eliminar <script src="Scripts/rectangle.js"></script> y reemplazar <script src="Scripts/myHiFiRectangle.js"></script> con <script src="Scripts/myHiFiRectangle.js" type="module"></script>. Eso soluciona un problema. la otra es que myHifiRectangle.js no crea una variable global (que debería dejar de usar de todos modos). Para obtener eso, agregue window.MyHiFiRectangle = MyHiFiRectangle;al final de myHifiRectangle.js.

    – conexión

    16 de enero de 2019 a las 22:25

avatar de usuario de curioso.netter
curioso.netter

Pasé por esto y tengo una solución con un tercer archivo js como módulo.
rectangle.js será igual y myHifiRectangle.js El archivo tiene una sola modificación.

import Rectangle from './rectangle.js';

export default class MyHiFiRectangle extends Rectangle {
      constructor(height, width) {
      super(height,width);
      this.foo= "bar";  
   }
}

Ahora, necesitamos un tercer archivo que será un archivo de módulo, digamos, script.js

import MyHiFiRectangle from './myHifiRectangle.js'

var v = new MyHiFiRectangle(2,4);
console.log(v.foo);

Ahora, el tercer archivo, script.js debe hacerse un módulo. Más sobre módulos aquí. Tengo los tres archivos bajo modelJS carpeta.

<script type="module" src="https://stackoverflow.com/modelJS/script.js"></script>

Ahora, cuando ejecute, debería ver la ‘barra’ impresa en la pestaña de la consola de la herramienta para desarrolladores.

  • ¡Excelente! no estaba al tanto de esto module atributo. Puede ser que Chrome no lo haya implementado al momento de escribir esta pregunta. Por cierto, pude lograrlo usando module atributo en mi propio archivo HTML como se menciona en mi propia respuesta. No necesité un separado script.js archivos para llamar a mis módulos. Realmente aprecio que te esfuerces en mi vieja pregunta. Aprendí algo nuevo hoy.

    – RBT

    17 de enero de 2019 a las 1:50

Avatar de usuario de RBT
RBT

También estoy agregando una respuesta después de recibir una pista de la respuesta de curiou.netter en este hilo.

Señalaré los errores de manera secuencial precisa en los archivos de código originales. Por cierto, pude solucionar el problema sin involucrar a más guión.js archivo:

  1. Al referirse a los módulos JS, el tipo de script debe ser módulo en cambio. me estaba refiriendo a myHiFiRectangle.js como un archivo JS normal usando origen etiquetar como:

    src="Scripts/myHiFiRectangle.js"
    

    también importé MyHiFiRectángulo módulo. Así es como el cabeza la etiqueta ahora se ve en el prueba.html archivo después de corregir este error:

    <head>
      <meta charset = "UTF-8">
      <title>Javascipt by Rasik Bihari Tiwari</title>
      <script type="module">
         import MyHiFiRectangle from './scripts/myHiFirectangle.js';
         var v = new MyHiFiRectangle(2,4);
         console.debug(v.foo);
      </script>
    </head>
    
  2. exportación predeterminada Faltaba declaración en myHiFiRectangle.js archivo. Cada clase debe exportarse como un módulo cuando debe usarse desde un lugar diferente. el rectificado myHiFiRectangle.js El archivo se ve a continuación:

    import Rectangle from './rectangle.js';
    export default class MyHiFiRectangle extends Rectangle {
      constructor(height, width) {
      super(height,width);
      this.foo= "bar";  
     }
    }
    
  3. Mis archivos de script tenían otro error en la forma en que estaba importando módulos.

    Manera incorrecta:

    import Rectangle from 'rectangle.js';
    import MyHiFiRectangle from '/scripts/myHiFirectangle.js';
    

    Provoca el siguiente error que se explica por sí mismo:

    TypeError no detectado: no se pudo resolver el especificador de módulo “rectangle.js”. Las referencias relativas deben comenzar con “/”, “./” o “../”.

    Forma correcta:

    import Rectangle from './rectangle.js';
    import MyHiFiRectangle from './scripts/myHiFirectangle.js';
    

  • Tenía mi extensión de archivo nombrada .mjs que rompió la importación. Así que mientras mantiene type="module" cambié la extensión del archivo a .js y funciona ahora.

    – Frizzante

    3 abr a las 11:45

Avatar de usuario de Mμ.
Mμ.

Me gustaría mostrarle una solución alternativa a lo que ha publicado @Andy Gaskell.

En primer lugar, necesita babel para asegurarse de que puede usar ES6 en su navegador. Esto es para garantizar que su código seguirá funcionando, ya que algunos navegadores (heredados como IE) no son compatibles con las características modernas de javascript (ES6 y posteriores), como la importación/exportación y las clases.

Puede agregar el siguiente script

`<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>`

antes que cualquier otro archivo javascript mencionado anteriormente.

En segundo lugar, si incluye sus clases de JavaScript en línea, el alcance de esas clases se vuelve global, incluso si residen en sus propios archivos js físicos.

He incluido un ejemplo de trabajo a continuación, lo he cambiado un poco para que funcione en el fragmento de código. Desea reemplazar el script con el script que contiene su archivo javascript como lo ha hecho en su código.

<!DOCTYPE html>
<html lang = "en">
   <head>
      <meta charset = "UTF-8">
      <title>Javascipt by Rasik Bihari Tiwari</title>
       <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>

      <!-- Replace them with script with src pointing to your javascript -->       
      <script type="text/javascript"> 
        class  Rectangle{
          constructor(height, width) {
            this.height = height;
            this.width = width;
          }
        }

        class MyHiFiRectangle extends Rectangle {
          constructor(height, width) {
              super(height,width);
              this.foo= "bar";  
         }
        }
           
       var v = new MyHiFiRectangle(2,4);
       console.log(v.foo);
       </script>
   </head>
   <body >

   </body>

</html>

ACTUALIZADO

OK. ¡Frío! Por cierto, si traigo toda la definición de la clase a la etiqueta del script de mi página html, entonces ni siquiera necesito hacer referencia a babel-core en la etiqueta principal. ¿Por qué sería necesario?

Es posible que lo necesite para navegadores que no admitan clases como IE. Pero, si la compatibilidad con los navegadores heredados no está entre sus requisitos, entonces no la necesita.

… ¿necesito siquiera las cosas de exportación e importación? ¿Cuál sería el significado de la exportación de módulos en un javascript nativo cuando cada clase es más o menos global?

De hecho, no necesitará las cosas de exportación e importación ya que sus clases son globales. Solo usa esto si desea usar el sistema de módulos. Si no usa importar/exportar, sus clases deberían ser globales y, por lo tanto, deberían funcionar. Pero en caso de que no fuera así de alguna manera. Te aseguras de que exista globalmente al adjuntarlo al objeto de la ventana de esta manera:

 window.myClass = class MyClass { /* Class definition */ }

  • OK. ¡Frío! Por cierto, si traigo toda la definición de clase a la etiqueta de secuencia de comandos de mi página html, entonces ni siquiera necesito hacer referencia babel-core en la etiqueta principal. ¿Por qué sería necesario? class La construcción ahora se admite de forma nativa en JavaScript a partir de ECMA-6. Yo debería no necesita un transpilador mientras trabaja con código javascript nativo. Los transpilers tal como están no juegan ningún papel, pero entran en acción cuando son invocados por algún paquete de módulos como webpack o browserify.

    – RBT

    15 de junio de 2017 a las 0:58


  • Ahora, la pregunta que queda es que todo esto no funciona cuando muevo mis clases a archivos js separados individuales. Lo que parece estar estallando en este momento es export y import sucediendo en archivos js individuales. Pero, si he incluido todos los archivos js (que contienen los archivos de clase) en forma secuencial/requerida (el orden en el que se hace referencia) en la página donde los estoy usando, ¿necesito las cosas de exportación e importación? ¿Cuál sería el significado de la exportación de módulos en un javascript nativo cuando cada clase es más o menos global?

    – RBT

    15 de junio de 2017 a las 1:05

  • De acuerdo. Entonces, según el sistema del módulo (suponiendo que estemos hablando de un día en que los navegadores actuales hayan implementado la cosa de exportar/importar): en el momento en que uso la declaración de exportación para una clase que reside en un archivo js propio, de repente se convierte en no- global por defecto y estará disponible para solo aquellos archivos de script que lo importan explícitamente usando la palabra clave de importación disponible en la especificación ECMA6. ¿Es una declaración justa para hacer?

    – RBT

    15 de junio de 2017 a las 3:18

  • Sí. Creo que eso es exacto. Puede ver que esto es cierto cuando intenta importar un archivo donde export ... no existe (en su aplicación js). El archivo que intenta importar dicho módulo se quejará. Esto se debe al sistema de módulos. El alcance del código se conserva dentro de un archivo, a menos que se importen o exporten.

    – Mμ.

    15 de junio de 2017 a las 3:24


  • En aras de la exhaustividad, ¿puede agregar una nota en su respuesta que indique que las palabras clave de exportación/importación no funcionan a partir de hoy, ya que todavía se encuentran en la fase de implementación (perteneciente a las especificaciones ECMA-6) por parte de varios proveedores de navegadores? Mi fragmento de código también funcionará solo si elimino las declaraciones de importación de exportación de ellos, ya que todas las clases son globales de forma predeterminada, incluso si residen en sus propios archivos físicos * .js.

    – RBT

    15 de junio de 2017 a las 5:08


Avatar de usuario de Andy Gaskell
Andy Gaskell

En la mayoría de los navegadores esto se habilita a través de indicador de función.

cromo: ir a about:flags y habilite las “Características de la plataforma web experimental”.

Firefox a partir de la versión 54: dom.moduleScripts.enabled.

Edge 15 o posterior: habilite “Características experimentales de JavaScript” en about:flags.

¿Ha sido útil esta solución?