module.exports ve Node.js ve ES6'da dışa aktarma varsayılanı


317

Düğüm module.exportsve ES6'lar arasındaki fark nedir export default? Ben export defaultNode.js 6.2.2 denediğimde neden "__ bir yapıcı değil" hatası alıyorum anlamaya çalışıyorum .

Ne çalışıyor

'use strict'
class SlimShady {
  constructor(options) {
    this._options = options
  }

  sayName() {
    return 'My name is Slim Shady.'
  }
}

// This works
module.exports = SlimShady

Ne gelmez işe

'use strict'
class SlimShady {
  constructor(options) {
    this._options = options
  }

  sayName() {
    return 'My name is Slim Shady.'
  }
}

// This will cause the "SlimShady is not a constructor" error
// if in another file I try `let marshall = new SlimShady()`
export default SlimShady

Yanıtlar:


401

Sorun şu

  • ES6 modüllerinin CommonJS'de nasıl taklit edildiği
  • modülü nasıl içe aktarırsınız

ES6 - CommonJS

Bunu yazarken, ES6 modüllerini yerel olarak hiçbir ortam desteklemez. Bunları Node.js'de kullanırken, modülleri CommonJS'ye dönüştürmek için Babel gibi bir şey kullanmanız gerekir. Ama bu tam olarak nasıl oluyor?

Birçok insan module.exports = ...buna eşdeğer export default ...ve exports.foo ...eşdeğer olduğunu düşünmektedir export const foo = .... Yine de bu tam olarak doğru değil, ya da en azından Babel'in bunu yapması değil.

ES6 defaultdışa aktarmaları aslında dışa aktarma olarak da adlandırılır , bunun dışında default"ayrılmış" bir ad ve bunun için özel bir sözdizimi desteği vardır. Babil'in adlandırılmış ve varsayılan dışa aktarmalarını nasıl derlediğine bir göz atalım:

// input
export const foo = 42;
export default 21;

// output
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
var foo = exports.foo = 42;
exports.default = 21; 

Burada, varsayılan dışa aktarmanın exports, tıpkı gibi , nesne üzerinde bir özellik haline geldiğini görebiliriz foo.

Modülü içe aktarın

Modülü iki şekilde içe aktarabiliriz: CommonJS veya ES6 importsözdizimi kullanarak .

Sorununuz: Aşağıdaki gibi bir şey yaptığınıza inanıyorum:

var bar = require('./input');
new bar();

bunun bariçin varsayılan dışa aktarma değeri atanır. Ancak yukarıdaki örnekte de görebileceğimiz gibi, varsayılan dışa aktarma özelliği atandı default!

Dolayısıyla, varsayılan dışa aktarmaya erişmek için aslında

var bar = require('./input').default;

ES6 modülü sözdizimini kullanırsak, yani

import bar from './input';
console.log(bar);

Babel onu

'use strict';

var _input = require('./input');

var _input2 = _interopRequireDefault(_input);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

console.log(_input2.default);

Her erişimin erişime bardönüştürüldüğünü görebilirsiniz .default.


Bunun için bir kopyamız yok mu?
Bergi

3
@Bergi: Ben tbh aramadım (utanç :(). Aynı sorun hakkında kesinlikle bir soru var, ama farklı bir şekilde sordum. Uygun bir şey bulursanız bana bildirin!
Felix Kling


1
Bunu şimdi nasıl ironik yapabilirim: D
Felix Kling

1
@djKianoosh: Kendiniz görün . İçin atamadan sonra module.exports, exportsve module.exportsatama böylece, farklı değerlere sahip exports.defaultsbir etkisi yoktur (çünkü module.exportsihraç alır budur). Başka bir deyişle, sadece sizin yaptığınız gibi module.exports = { ... }.
Felix Kling

1

Export varsayılan ve export const foo'yu kullanmak için projenizde babel'i doğru yapılandırmanız gerekiyor

npm install --save-dev @babel/plugin-proposal-export-default-from

sonra .babelrc içine aşağıdaki konfigürasyonu ekleyin

"plugins": [ 
       "@babel/plugin-proposal-export-default-from"
      ]

1

Felix Kling, modülle adlandırılmış dışa aktarmaların yanı sıra dışa aktarma varsayılanının nasıl yapılacağını merak eden herkes için bu ikisi üzerinde harika bir karşılaştırma yaptı.

module.exports = new DAO()
module.exports.initDAO = initDAO // append other functions a named export

// now you have
let DAO = require('_/helpers/DAO');
// DAO by default is exported class or function
DAO.initDAO()

-61

tl; dr bunun çalışması için gereken veya içe aktarılan dosya SlimShadyBabel ile derlenmelidir 'use strict'.

babel-cliBaşlangıçta bu hatayla karşılaştığım projede 6.18.0 kullanıyorum .

'use strict'Kötü Haber Ayılar Olmadan

var SlimShady = require('./slim-shady');
var marshall = new SlimShady();  // uh, oh...

'katı kullanın', lütfen

'use strict'
import SlimShady from './slim-shady'
var marshall = new SlimShady()  // all good in the hood

13
Bu anlamlı değil. importBildirimleri kullanan her kaynak bir modüldür ve bunlar zaten katıdır. Asıl fark, ithal etmeyi istemekle ilgilidir.
Bergi

1
Mantıklı olan, importyerine requireve export defaultyerine kullanmaktır exports.default.
Corey Alix


104
Bu stackoverflow
Jimi

4
@Jimi Bunun nedeni, sitenin tamamında en çok dördüncü oylanan cevap olmasıdır.
pppery
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.