Klasy Node.js ES6 z require

104

Do tej pory tworzyłem klasy i moduły w node.jsnastępujący sposób:

    var fs = require('fs');

var animalModule = (function () {
    /**
     * Constructor initialize object
     * @constructor
     */
    var Animal = function (name) {
        this.name = name;
    };

    Animal.prototype.print = function () {
        console.log('Name is :'+ this.name);
    };

    return {
        Animal: Animal
    }
}());

module.exports = animalModule;

Teraz z ES6 możesz tworzyć „rzeczywiste” klasy, takie jak to:

class Animal{

 constructor(name){
    this.name = name ;
 }

 print(){
    console.log('Name is :'+ this.name);
 }
}

Przede wszystkim uwielbiam to :), ale rodzi pytanie. Jak to wykorzystać w połączeniu ze node.jsstrukturą modułu?

Powiedzmy, że masz klasę, w której chcesz użyć modułu do celów demonstracyjnych, powiedz, że chcesz użyć fs

więc tworzysz swój plik:


Animal.js

var fs = require('fs');
class Animal{

 constructor(name){
    this.name = name ;
 }

 print(){
    console.log('Name is :'+ this.name);
 }
}

Czy to byłby właściwy sposób?

Ponadto, jak udostępnić tę klasę innym plikom w moim projekcie węzła? Czy nadal byłbyś w stanie rozszerzyć tę klasę, jeśli używasz jej w osobnym pliku?

Mam nadzieję, że część z Was będzie w stanie odpowiedzieć na te pytania :)

Marc Rasmussen
źródło
3
Po prostu potraktuj nazwę klasy ES6 tak samo, jakbyś traktował nazwę konstruktora w sposób ES5. Są jednym i tym samym. Składnia ES6 jest po prostu cukrem składniowym i tworzy dokładnie ten sam podstawowy prototyp, funkcję konstruktora i obiekty.
jfriend00
To IIFE, które tworzy twój, animalModulejest całkiem bezcelowe w module węzła, który i tak ma własny zakres modułu.
Bergi

Odpowiedzi:

157

Tak, twój przykład zadziała dobrze.

Jeśli chodzi o eksponowanie swoich zajęć, możesz je exporttraktować jak wszystko inne:

class Animal {...}
module.exports = Animal;

Lub krócej:

module.exports = class Animal {

};

Po zaimportowaniu do innego modułu możesz traktować go tak, jakby był zdefiniowany w tym pliku:

var Animal = require('./Animal');

class Cat extends Animal {
    ...
}
rossipedia
źródło
8
Możesz także zrobić coś takiego jak module.exports = class Animal {}
Paul
to prawda, ciągle zapominam, że możesz nazywać rzeczy podczas przydziału.
rossipedia
Sprowadza się do stylu i przejrzystości kodu. module.exportsjest zwykle używany do anonimowego eksportu, natomiast exportjest używany do nazwanego eksportu. Jest to podstawowa zaleta kodowania (można by rzec), która może pomóc innym wiedzieć, jak zaimportować twoją klasę, moduł i tak dalej.
greg.arnott,
7
module.exports = Animal;byłaby odpowiedzią lub najbardziej bezpośrednim odpowiednikiem pytania i jest ważna wraz z const Animal = require('./animal');kodem wywołującym. Czy możesz zaktualizować swoją odpowiedź, aby ją uwzględnić?
niedz.
1
Dzięki stary, walczyłem z poprawnym importowaniem zajęć przez około 2 godziny.
kiwicomb123
11

Po prostu potraktuj nazwę klasy ES6 tak samo, jakbyś traktował nazwę konstruktora w sposób ES5. Są jednym i tym samym.

Składnia ES6 jest po prostu cukrem składniowym i tworzy dokładnie ten sam podstawowy prototyp, funkcję konstruktora i obiekty.

A więc w przykładzie z ES6 z:

// animal.js
class Animal {
    ...
}

var a = new Animal();

module.exports = {Animal: Animal};

Możesz po prostu traktować Animaljak konstruktor swojego obiektu (tak samo, jak zrobiłbyś to w ES5). Możesz wyeksportować konstruktora. Możesz wywołać konstruktora za pomocą new Animal(). Korzystanie z niego jest takie samo. Jedynie składnia deklaracji jest inna. Nadal istnieje taki, Animal.prototypektóry zawiera wszystkie twoje metody. Sposób ES6 naprawdę tworzy ten sam wynik kodowania, tylko z bardziej wyszukaną / ładniejszą składnią.


Po stronie importu byłoby to używane w następujący sposób:

const Animal = require('./animal.js').Animal;

let a = new Animal();

Ten schemat eksportuje konstruktora Animal jako .Animalwłaściwość, która pozwala wyeksportować więcej niż jedną rzecz z tego modułu.

Jeśli nie musisz eksportować więcej niż jednej rzeczy, możesz to zrobić:

// animal.js
class Animal {
    ...
}

module.exports = Animal;

A następnie zaimportuj go za pomocą:

const Animal = require('./animal.js');

let a = new Animal();
jfriend00
źródło
Nie wiem dlaczego, ale to po prostu mi nie wyszło. module.exports = Animalto jedyne rozwiązanie, które działa.
Sam,
1
@Sam - To, co pokazuje mój eksport, potrzebuje innego require()niż to, co pokazuje twój eksport, więc dlatego jeden miałby działać, a drugi nie. Musisz dopasować sposób działania importu do sposobu zdefiniowania eksportu. Więcej szczegółów wyjaśniających to dodane do mojej odpowiedzi.
jfriend00
6

Sposób wymagania ES6 to import. Możesz exportswoją klasę i zaimportować ją gdzie indziej, używając import { ClassName } from 'path/to/ClassName'składni.

import fs from 'fs';
export default class Animal {

  constructor(name){
    this.name = name ;
  }

  print(){
    console.log('Name is :'+ this.name);
  }
}

import Animal from 'path/to/Animal.js';
Fan Jin
źródło
4
Dobrze byłoby wyjaśnić, że jest to opcja, ale nie jest to wymóg. To jest składnia modułu ES6, ale nadal możesz używać klasy ES6 z normalnymi eksportami CommonJS Node. Nie ma wymogu używania składni eksportu ES6 z klasami. Nazywanie tego The ES6 wayjest nieco mylące.
loganfsmyth
2
To prawda, to osobiste preferencje. Osobiście użyłbym importover requiretylko ze względu na spójność składni.
Fan Jin
2
Tak, to solidne podejście i ja też to robię, ale pamiętaj, że sposób, w jaki Babel importwspółpracuje z modułami CommonJS, nie jest prawdopodobny, co zakończy się działaniem w Node, więc może wymagać zmian w kodzie w przyszłości, aby był kompatybilny z Node bez Babel .
loganfsmyth
4
Moduły ES6 (import i eksport) są nadal w
fazie
Aby dodać do punktu @ dorking. Węzeł 10.15.3 to wersja LTS (wsparcie długoterminowe) i będzie dostępna do kwietnia 2020 r. Dodatkowe szczegóły tutaj: nodejs.org/en/about/releases
gtzilla
1

Używanie klas w węźle -

Tutaj wymagamy modułu ReadWrite i wywołujemy metodę makeObject (), która zwraca obiekt klasy ReadWrite. Które używamy do wywoływania metod. index.js

const ReadWrite = require('./ReadWrite').makeObject();
const express = require('express');
const app = express();

class Start {
  constructor() {
    const server = app.listen(8081),
     host = server.address().address,
     port = server.address().port
    console.log("Example app listening at http://%s:%s", host, port);
    console.log('Running');

  }

  async route(req, res, next) {
    const result = await ReadWrite.readWrite();
    res.send(result);
  }
}

const obj1 = new Start();
app.get('/', obj1.route);
module.exports = Start;

ReadWrite.js

Tutaj tworzymy metodę makeObject, która zapewnia, że ​​obiekt zostanie zwrócony, tylko jeśli obiekt nie jest dostępny.

class ReadWrite {
    constructor() {
        console.log('Read Write'); 
        this.x;   
    }
    static makeObject() {        
        if (!this.x) {
            this.x = new ReadWrite();
        }
        return this.x;
    }
    read(){
    return "read"
    }

    write(){
        return "write"
    }


    async readWrite() {
        try {
            const obj = ReadWrite.makeObject();
            const result = await Promise.all([ obj.read(), obj.write()])
            console.log(result);
            check();
            return result
        }
        catch(err) {
            console.log(err);

        }
    }
}
module.exports = ReadWrite;

Więcej wyjaśnień można znaleźć pod adresem https://medium.com/@nynptel/node-js-boiler-plate-code-using-singleton-classes-5b479e513f74

Nayan Patel
źródło
0

W pliku klasy możesz użyć:

module.exports = class ClassNameHere {
 print() {
  console.log('In print function');
 }
}

lub możesz użyć tej składni

class ClassNameHere{
 print(){
  console.log('In print function');
 }
}

module.exports = ClassNameHere;

Z drugiej strony, aby użyć tej klasy w jakimkolwiek innym pliku, musisz wykonać następujące kroki. Najpierw wymagaj tego pliku przy użyciu następującej składni: const anyVariableNameHere = require('filePathHere');

Następnie utwórz obiekt const classObject = new anyVariableNameHere();

Następnie możesz użyć, classObjectaby uzyskać dostęp do rzeczywistych zmiennych klas

Burhan Maseel
źródło