Làm thế nào để xuất đúng một lớp ES6 trong Node 4?


115

Tôi đã xác định một lớp trong một mô-đun:

"use strict";

var AspectTypeModule = function() {};
module.exports = AspectTypeModule;

var AspectType = class AspectType {
    // ...    
};

module.export.AspectType = AspectType;

Nhưng tôi nhận được thông báo lỗi sau:

TypeError: Cannot set property 'AspectType' of undefined
    at Object.<anonymous> (...\AspectType.js:30:26)
    at Module._compile (module.js:434:26)
    ....

Làm cách nào để xuất lớp này và sử dụng nó trong một mô-đun khác? Tôi đã thấy các câu hỏi SO khác, nhưng tôi nhận được thông báo lỗi khác khi tôi cố gắng triển khai các giải pháp của họ.


2
Trong ES6, bạn không cần 'use strict'trong một mô-đun hoặc lớp học; đó là hành vi mặc định. Tham khảo 10.2.1 Mã chế độ nghiêm ngặt
Jason Leach

Câu trả lời:


117

Nếu bạn đang sử dụng ES6 trong Node 4, bạn không thể sử dụng cú pháp mô-đun ES6 mà không có bộ chuyển tiếp, nhưng các mô-đun CommonJS (mô-đun tiêu chuẩn của Node) hoạt động tương tự.

module.export.AspectType

nên là

module.exports.AspectType

do đó thông báo lỗi "Không thể đặt thuộc tính 'AspectType' của không xác định" bởi vì module.export === undefined.

Ngoài ra, đối với

var AspectType = class AspectType {
    // ...    
};

bạn có thể chỉ cần viết

class AspectType {
    // ...    
}

và về cơ bản cùng một hành vi.


27
OMG exportthay vì exports, làm thế nào tôi bỏ lỡ điều đó?
Jérôme Verstrynge

1
ở cuối tôi đặt module.exports = ClassNamevà nó hoạt động tốt
David Welborn

113
// person.js
'use strict';

module.exports = class Person {
   constructor(firstName, lastName) {
       this.firstName = firstName;
       this.lastName = lastName;
   }

   display() {
       console.log(this.firstName + " " + this.lastName);
   }
}

 

// index.js
'use strict';

var Person = require('./person.js');

var someone = new Person("First name", "Last name");
someone.display();

2
@sitrakay, bạn thực sự nên thêm giải thích về cách điều này khắc phục câu hỏi.
Alexis Tyler

điều này gây ra lỗi: Uncaught TypeError: Không thể gán chỉ đọc thuộc tính 'xuất khẩu' của đối tượng '# <Đối tượng>' tại sao điều này lại được ủng hộ nhiều như vậy?
henon

Tôi nghĩ rằng việc đặt toàn bộ định nghĩa lớp bên trong bài tập xuất khẩu là một mô hình phản đối khi một dòng duy nhất ở cuối cũng làm điều tương tự.
user1944491

44

Với ECMAScript 2015, bạn có thể xuất và nhập nhiều lớp như thế này

class Person
{
    constructor()
    {
        this.type = "Person";
    }
}

class Animal{
    constructor()
    {
        this.type = "Animal";
    }
}

module.exports = {
    Person,
    Animal
};

thì nơi bạn sử dụng chúng:

const { Animal, Person } = require("classes");

const animal = new Animal();
const person = new Person();

Trong trường hợp xung đột tên hoặc bạn thích tên khác, bạn có thể đổi tên chúng như sau:

const { Animal : OtherAnimal, Person : OtherPerson} = require("./classes");

const animal = new OtherAnimal();
const person = new OtherPerson();

1
Sai lầm. Lý do: Nếu bạn đang sử dụng ES6 trong Node 4, bạn không thể sử dụng cú pháp mô-đun ES6 mà không có bộ chuyển tiếp, nhưng các mô-đun CommonJS (mô-đun tiêu chuẩn của Node) hoạt động tương tự. (như trên)
AaronHS

Ngoài ra, bạn không nên khai báo hai lớp trong cùng một tệp
ariel

Có thể có các lớp "private-like" (hỗ trợ một lớp chung duy nhất) trong cùng một tệp, miễn là các lớp riêng không được xuất. Nó cũng có thể chấp nhận được nếu bạn chưa cấu trúc lại chúng thành hai tệp. Khi làm như vậy, đừng quên chia các bài kiểm tra của bạn thành các tệp riêng biệt. Hoặc chỉ làm những gì bạn cần cho tình huống của bạn.
TamusJRoyce 17/02/19

@AaronHS sự khác biệt chính xác mà bạn đang đề cập là gì? Nó cũng không rõ ràng trong câu trả lời "ở trên".
user1944491

16

Sử dụng

// aspect-type.js
class AspectType {

}

export default AspectType;

Sau đó để nhập nó

// some-other-file.js
import AspectType from './aspect-type';

Đọc http://babeljs.io/docs/learn-es2015/#modules để biết thêm chi tiết


1
Tôi nhận được một SyntaxError: Unexpected reserved word, bạn có thể cung cấp một ví dụ mã đầy đủ không?
Jérôme Verstrynge

9
xuất và nhập chưa được triển khai trong V8 mà nút sử dụng. Bạn vẫn sẽ cần phải sử dụngmodule.exports
Evan Lucas

2
... hoặc transpile (tức là babel), thực sự. NodeJS có hầu hết các tính năng của ES6 .. ngoại trừ import / export(vẫn đúng, tháng 5 năm 2017).
Frank Nocke

12

biểu thức lớp có thể được sử dụng cho đơn giản.

 // Foo.js
'use strict';

// export default class Foo {}
module.exports = class Foo {}

-

// main.js
'use strict';

const Foo = require('./Foo.js');

let Bar = new class extends Foo {
  constructor() {
    super();
    this.name = 'bar';
  }
}

console.log(Bar.name);

4
Chỉ là một cảnh báo, trong Node, điều này phụ thuộc vào thứ tự tải mô-đun. Vì vậy, hãy cẩn thận với việc sử dụng này. Nếu bạn chuyển đổi tên của các tệp này xung quanh ví dụ sẽ không hoạt động.
Dustin

12

Tôi chỉ viết nó theo cách này

trong tệp AspectType:

class AspectType {
  //blah blah
}
module.exports = AspectType;

và nhập nó như thế này:

const AspectType = require('./AspectType');
var aspectType = new AspectType;

10

Một số câu trả lời khác gần giống nhau, nhưng thành thật mà nói, tôi nghĩ bạn tốt hơn nên sử dụng cú pháp rõ ràng và đơn giản nhất. OP đã yêu cầu một phương tiện xuất một lớp trong ES6 / ES2015. Tôi không nghĩ rằng bạn có thể làm sạch hơn thế này:

'use strict';

export default class ClassName {
  constructor () {
  }
}

2
Sai lầm. Lý do: Nếu bạn đang sử dụng ES6 trong Node 4, bạn không thể sử dụng cú pháp mô-đun ES6 mà không có bộ chuyển tiếp, nhưng các mô-đun CommonJS (mô-đun tiêu chuẩn của Node) hoạt động tương tự. (như trên)
AaronHS

3
Ai vẫn đang sử dụng Node 4? Tôi nghĩ đây là câu trả lời xác đáng cho 99% mọi người.
Đóng thùng vào

Nó có nghĩa đen trong tiêu đề của câu hỏi.
AaronHS

0

Tôi đã từng gặp vấn đề tương tự. Những gì tôi tìm thấy là tôi đã gọi đối tượng nhận của mình cùng tên với tên lớp. thí dụ:

const AspectType = new AspectType();

điều này làm mọi thứ rối tung lên theo cách đó ... hy vọng điều này sẽ giúp


0

Đôi khi tôi cần khai báo nhiều lớp trong một tệp hoặc tôi muốn xuất các lớp cơ sở và giữ nguyên tên của chúng được xuất vì trình soạn thảo JetBrains của tôi hiểu điều đó tốt hơn. Tôi chỉ sử dụng

global.MyClass = class MyClass { ... };

Và một nơi khác:

require('baseclasses.js');
class MySubclass extends MyClass() { ... }

1
Đây là một cách làm không tốt ... nó sẽ dẫn đến va chạm vào một ngày nào đó.
Brad

Vâng tốt. Không có vấn đề về va chạm trong các dự án sở hữu. Và nếu bạn hoàn toàn nhập các lớp thông qua request / module.exports, bạn chỉ cần chuyển vấn đề sang tên mô-đun.
Jelmer Jellema

Ngừng cố gắng viết PHP bằng JavaScript: P Bỏ chuyện cười - như mọi người đã nói, đây chỉ là bạn đang tự giải quyết các vấn đề sau này. Quả địa cầu là một ý tưởng rất tồi, không tốt, rất xấu.
robertmain,

1
Chúng dành cho những người không thể theo dõi mã của riêng họ. Đừng quên các tên tệp được sử dụng trong request cũng là hình cầu. Giáo điều phi toàn cầu cũng có giới hạn của nó.
Jelmer Jellema

Chà, @TimHobbs, những điều bọn trẻ nói .. Những thứ như "Chúng chỉ là, giai đoạn." Đó chính xác là kiểu lý lẽ mà bạn nghe từ những người thiếu lý lẽ thực tế. Bạn biết. Ngay cả NodeJs cũng sử dụng hình cầu. Thậm chí không có vấn đề gì khi bạn có một khuôn khổ được xác định rõ với các hình cầu được ghi chép đầy đủ. Thật vui khi biết rằng sau ngần ấy năm học, tốt nghiệp kiêm chức và nuôi sống bản thân và gia đình trong 20 năm nay, đó chỉ là "dù sao thì tôi cũng muốn làm gì". Cho tôi một cuộc tranh cãi hoặc ngừng hành động như một đứa trẻ.
Jelmer Jellema 17/12/18
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.