Node.js คลาส ES6 ที่ต้องการ


106

จนถึงตอนนี้ฉันได้สร้างคลาสและโมดูลnode.jsด้วยวิธีต่อไปนี้:

    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;

ตอนนี้ด้วย ES6 คุณสามารถสร้างคลาส "จริง" ได้ดังนี้:

class Animal{

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

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

ตอนนี้ก่อนอื่นฉันชอบสิ่งนี้ :) แต่มันทำให้เกิดคำถาม คุณใช้สิ่งนี้ร่วมกับnode.jsโครงสร้างโมดูลได้อย่างไร?

สมมติว่าคุณมีชั้นเรียนที่คุณต้องการใช้โมดูลเพื่อการสาธิตบอกว่าคุณต้องการใช้ fs

ดังนั้นคุณจึงสร้างไฟล์ของคุณ:


Animal.js

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

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

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

นี่จะเป็นวิธีที่ถูกต้องหรือไม่?

นอกจากนี้คุณเปิดเผยคลาสนี้กับไฟล์อื่น ๆ ภายในโครงการโหนดของฉันได้อย่างไร และคุณจะยังสามารถขยายคลาสนี้ได้หรือไม่ถ้าคุณใช้มันในไฟล์แยกต่างหาก

ฉันหวังว่าพวกคุณบางคนจะสามารถตอบคำถามเหล่านี้ได้ :)


3
เพียงใช้ชื่อคลาส ES6 เหมือนกับที่คุณใช้กับชื่อตัวสร้างด้วยวิธี ES5 พวกเขาเป็นหนึ่งเดียวกัน ไวยากรณ์ ES6 เป็นเพียงน้ำตาลในการสังเคราะห์และสร้างต้นแบบต้นแบบฟังก์ชันตัวสร้างและวัตถุที่เหมือนกันทุกประการ
jfriend00

IIFE ที่สร้างของคุณanimalModuleนั้นค่อนข้างไม่มีจุดหมายในโมดูลโหนดที่มีขอบเขตโมดูลของตัวเอง
Bergi

คำตอบ:


164

ใช่ตัวอย่างของคุณใช้ได้ดี

สำหรับการเปิดเผยชั้นเรียนของคุณคุณสามารถexportเลือกชั้นเรียนได้เช่นเดียวกับสิ่งอื่น ๆ :

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

หรือสั้นกว่า:

module.exports = class Animal {

};

เมื่อนำเข้าสู่โมดูลอื่นแล้วคุณสามารถใช้งานได้ราวกับว่ามีการกำหนดไว้ในไฟล์นั้น:

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

class Cat extends Animal {
    ...
}

8
คุณยังสามารถทำบางอย่างเช่น module.exports = class Animal {}
Paul

นั่นเป็นเรื่องจริงฉันมักจะลืมไปว่าคุณสามารถตั้งชื่อสิ่งต่างๆระหว่างการมอบหมายงานได้
rossipedia

7
module.exports = Animal;จะเป็นคำตอบหรือตรงที่สุดเทียบเท่ากับคำถามและใช้ได้พร้อมกับconst Animal = require('./animal');รหัสโทร คุณสามารถอัปเดตคำตอบของคุณเพื่อรวมไว้ได้หรือไม่
ดวงอาทิตย์

1
ขอบคุณเพื่อน ๆ ฉันต่อสู้กับการนำเข้าคลาสที่ทำงานได้อย่างถูกต้องเป็นเวลา 2 ชั่วโมง
kiwicomb123

1
โปรดสังเกตว่าclass Animal {...} module.exports = Animalและmodule.exports = class Animal {...}ไม่เหมือนกัน: ในรูปแบบหลังคุณไม่สามารถใช้new Animal()ในไฟล์ที่ต้องการได้เนื่องจากชื่อคลาสสามารถเข้าถึงได้จากในคลาสเท่านั้น
wortwart

11

เพียงใช้ชื่อคลาส ES6 เหมือนกับที่คุณใช้กับชื่อตัวสร้างด้วยวิธี ES5 พวกเขาเป็นหนึ่งเดียวกัน

ไวยากรณ์ ES6 เป็นเพียงน้ำตาลในการสังเคราะห์และสร้างต้นแบบต้นแบบฟังก์ชันตัวสร้างและวัตถุที่เหมือนกันทุกประการ

ดังนั้นในตัวอย่าง ES6 ของคุณด้วย:

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

var a = new Animal();

module.exports = {Animal: Animal};

คุณสามารถปฏิบัติAnimalเหมือนตัวสร้างวัตถุของคุณ (เช่นเดียวกับที่คุณทำใน ES5) คุณสามารถส่งออกตัวสร้าง คุณสามารถเรียกตัวสร้างด้วยnew Animal(). ทุกอย่างเหมือนกันสำหรับการใช้งาน เฉพาะไวยากรณ์การประกาศเท่านั้นที่แตกต่างกัน ยังAnimal.prototypeมีวิธีการทั้งหมดของคุณอยู่ วิธี ES6 สร้างผลลัพธ์การเข้ารหัสที่เหมือนกันจริงๆโดยใช้ไวยากรณ์ที่ดีกว่า / ดีกว่า


ในด้านการนำเข้าสิ่งนี้จะถูกใช้ในลักษณะนี้:

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

let a = new Animal();

โครงร่างนี้ส่งออกตัวสร้างสัตว์เป็น.Animalคุณสมบัติซึ่งช่วยให้คุณส่งออกมากกว่าหนึ่งสิ่งจากโมดูลนั้น

หากคุณไม่ต้องการส่งออกมากกว่าหนึ่งสิ่งคุณสามารถทำได้:

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

module.exports = Animal;

จากนั้นนำเข้าด้วย:

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

let a = new Animal();

ฉันไม่รู้ว่าทำไม แต่มันไม่ได้ผลสำหรับฉัน module.exports = Animalเป็นทางออกเดียวที่ใช้ได้ผล
แซม

1
@Sam - สิ่งที่การส่งออกของฉันแสดงให้เห็นว่าต้องการความแตกต่างrequire()จากสิ่งที่การส่งออกของคุณแสดงดังนั้นนั่นอาจเป็นเหตุผลว่าทำไมสิ่งหนึ่งจึงใช้ได้ผลและอีกอย่างจะไม่ คุณต้องจับคู่วิธีการทำงานของการนำเข้ากับวิธีกำหนดการส่งออก รายละเอียดเพิ่มเติมเพื่ออธิบายสิ่งนี้เพิ่มเข้ามาในคำตอบของฉัน
jfriend00

6

วิธี ES6 importของจำเป็นต้องเป็น คุณสามารถexportนำเข้าคลาสของคุณและนำเข้าที่อื่นโดยใช้import { ClassName } from 'path/to/ClassName'ไวยากรณ์

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';

4
จะเป็นการดีที่จะชี้แจงว่านี่เป็นทางเลือก แต่ไม่ใช่ข้อกำหนด นี่คือไวยากรณ์ของโมดูล ES6 แต่คุณยังสามารถใช้คลาส ES6 กับการส่งออก CommonJS ของ Node ได้ ไม่มีข้อกำหนดให้คุณใช้ไวยากรณ์การส่งออก ES6 กับคลาส เรียกได้ว่าThe ES6 wayค่อนข้างทำให้เข้าใจผิด
loganfsmyth

2
ที่แท้มันเป็นความชอบส่วนตัว ส่วนตัวผมจะใช้importมากกว่าrequireเพียงเพื่อประโยชน์ของความสอดคล้องไวยากรณ์
Fan Jin

2
ใช่มันเป็นแนวทางที่มั่นคงและฉันก็ทำเช่นกันโปรดจำไว้ว่าวิธีที่ Babel importทำงานร่วมกับโมดูล CommonJS นั้นไม่น่าจะเป็นไปได้ว่าอะไรจะจบลงด้วยการทำงานในโหนดดังนั้นจึงอาจต้องมีการเปลี่ยนแปลงโค้ดในอนาคตเพื่อให้เข้ากันได้กับ Node โดยไม่มี Babel .
loganfsmyth

4
โมดูล ES6 (นำเข้าและส่งออก) ยังคงทดลองอยู่ในโหนด 10 และจำเป็นต้องเปิดใช้งานเมื่อเรียกใช้โหนด
dcorking

เพื่อเพิ่มไปยังจุดของ @ dorking โหนด 10.15.3 เป็นเวอร์ชัน LTS (การสนับสนุนระยะยาว) และจะมีถึงเดือนเมษายน 2020 รายละเอียดเพิ่มเติมที่นี่: nodejs.org/en/about/releases
gtzilla

1

การใช้คลาสในโหนด -

ที่นี่เราต้องการโมดูล ReadWrite และเรียกใช้ makeObject () ซึ่งส่งคืนอ็อบเจ็กต์ของคลาส ReadWrite ที่เราใช้เรียกเมธอด. 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

ที่นี่เราสร้างเมธอด makeObject ซึ่งทำให้แน่ใจว่าอ็อบเจ็กต์ถูกส่งคืนเฉพาะเมื่ออ็อบเจ็กต์ไม่พร้อมใช้งาน

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;

สำหรับคำอธิบายเพิ่มเติมไปที่https://medium.com/@nynptel/node-js-boiler-plate-code-using-singleton-classes-5b479e513f74


0

ในไฟล์คลาสคุณสามารถใช้:

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

หรือคุณสามารถใช้ไวยากรณ์นี้

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

module.exports = ClassNameHere;

ในทางกลับกันในการใช้คลาสนี้ในไฟล์อื่น ๆ คุณต้องทำตามขั้นตอนเหล่านี้ ขั้นแรกต้องการไฟล์นั้นโดยใช้ไวยากรณ์นี้: const anyVariableNameHere = require('filePathHere');

จากนั้นสร้างวัตถุ const classObject = new anyVariableNameHere();

หลังจากนี้คุณสามารถใช้classObjectเพื่อเข้าถึงตัวแปรคลาสจริง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.