developer tip

module.exports 대 Node.js의 내보내기

optionbox 2020. 9. 30. 10:25
반응형

module.exports 대 Node.js의 내보내기


Node.js 모듈에서 다음 계약을 찾았습니다.

module.exports = exports = nano = function database_module(cfg) {...}

내가 무슨 일을 사이에 다른 궁금 module.exports하고 exports왜 모두 여기에 사용됩니다.


설정 module.exports하면 database_module함수가 required. 단순히 설정 exports하면 노드가 객체 module.exports참조를 내보내므로 함수를 내보낼 수 없습니다 . 다음 코드는 사용자가 함수를 호출하는 것을 허용하지 않습니다.

module.js

다음은 작동하지 않습니다.

exports = nano = function database_module(cfg) {return;}

module.exports가 설정된 경우 다음이 작동합니다 .

module.exports = exports = nano = function database_module(cfg) {return;}

콘솔

var func = require('./module.js');
// the following line will **work** with module.exports
func();

기본적으로 node.jsexports현재 참조 하는 객체를 내 보내지 않지만 exports원래 참조 하는 속성을 내 보냅니다 . Node.js 는 객체 module.exports참조를 내보내 지만 함수처럼 호출 할 수 있습니다.


두 번째로 중요한 이유

그들은 둘을 설정 module.exports하고 exports확인하기 위해 exports사전에 수출 객체를 참조하지 않습니다. 두 가지 모두를 exports속기로 설정 하고 나중에 길을 따라 잠재적 인 버그를 피할 수 있습니다.

exports.prop = true대신 사용 module.exports.prop = true하면 문자 저장하고 혼동을 피할 수 있습니다.


질문에 대한 답변이 오래 전부터 받아 들여졌지만 2 센트를 공유하고 싶습니다.

파일의 맨 처음에 다음과 같은 내용이 있다고 상상할 수 있습니다.

var module = new Module(...);
var exports = module.exports;

여기에 이미지 설명 입력

따라서 무엇을하든 기억하고 다른 곳에서 해당 모듈을 요구할 때 모듈에서 반환 module.exports되지 않습니다 exports.

따라서 다음과 같이 할 때 :

exports.a = function() {
    console.log("a");
}
exports.b = function() {
    console.log("b");
}

module.exports가 가리키는 객체에 두 개의 함수 'a'와 'b'를 추가하므로 typeof반환 결과는 다음과 object같습니다.{ a: [Function], b: [Function] }

물론 이것은 module.exports대신이 예제에서 사용하는 경우 얻을 수있는 동일한 결과 입니다 exports.

module.exports가 내 보낸 값의 컨테이너처럼 동작하도록하려는 경우입니다. 반면 생성자 함수 만 내보내려면 module.exports또는 exports; (내보내기가 아닌 무언가가 필요할 때 module.exports가 반환된다는 것을 다시 기억하십시오) 사용에 대해 알아야 합니다.

module.exports = function Something() {
    console.log('bla bla');
}

이제 typeof 반환 결과는 다음 'function'과 같이 요청하고 즉시 호출 할 수 있습니다
var x = require('./file1.js')();. 반환 결과를 함수로 덮어 쓰기 때문입니다.

그러나 exports다음과 같은 것을 사용할 수 없습니다.

exports = function Something() {
    console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function

를 사용 exports하면 참조가 더 이상 module.exports가리키는 객체를 '지키지' 않기 때문에와 사이 exportsmodule.exports더 이상 관계가 없습니다. 이 경우 module.exports는 여전히 {}반환 될 빈 객체 가리 킵니다 .

다른 주제에서 수락 된 답변도 도움이 될 것입니다. Javascript가 참조로 전달됩니까?


기본적으로 대답은 require문을 통해 모듈이 필요할 때 실제로 일어나는 일에 있습니다. 모듈이 처음으로 필요하다고 가정합니다.

예를 들면 :

var x = require('file1.js');

file1.js의 내용 :

module.exports = '123';

위의 문이 실행되면 Module객체가 생성됩니다. 생성자 함수는 다음과 같습니다.

function Module(id, parent) {
    this.id = id;
    this.exports = {};
    this.parent = parent;
    if (parent && parent.children) {
        parent.children.push(this);
    }

    this.filename = null;
    this.loaded = false;
    this.children = [];
}

보시다시피 각 모듈 객체에는 name 속성이 exports있습니다. 이것은 결국의 일부로 반환되는 것입니다 require.

require의 다음 단계는 file1.js의 내용을 아래와 같은 익명 함수로 래핑하는 것입니다.

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
});

그리고이 익명 함수는 다음과 같은 방식으로 호출됩니다. module여기서는 Module앞서 만든 Object를 참조합니다 .

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
}) (module.exports,require, module, "path_to_file1.js","directory of the file1.js");

함수 내부에서 볼 수 있듯이 exports형식 인수는 module.exports. 본질적으로 모듈 프로그래머에게 제공되는 편의입니다.

그러나 이러한 편리함은주의해서 실행해야합니다. 어쨌든 새 개체를 내보내기에 할당하려는 경우이 방법으로 수행해야합니다.

exports = module.exports = {};

우리가 방법 다음을 수행하면 잘못된 방법을 , module.exports여전히 모듈 인스턴스의 일부로 생성 된 객체를 가리키는 것입니다.

exports = {};

결과적으로 위의 exports 객체에 아무것도 추가해도 module.exports 객체에 영향을 미치지 않으며 require의 일부로 내보내거나 반환되지 않습니다.


처음에는, module.exports=exportsrequire함수가 module.exports참조 하는 객체를 반환합니다 .

를 들어 객체 에 속성추가 하면 exports.a=1module.exports 및 exports는 여전히 동일한 객체를 참조합니다. 따라서 require를 호출하고 모듈을 변수에 할당하면 변수에는 속성 a가 있고 그 값은 1입니다.

우리는하지만 오버라이드 (override) 중 하나를 예를 들어 exports=function(){}, 그들은는 다른 지금 : 수출은 새로운 객체를 참조하고 module.exports 원본 객체를 참조하십시오. 그리고 파일이 필요한 경우 module.exports가 새 개체를 참조하지 않기 때문에 새 개체를 반환하지 않습니다.

나를 위해 새 속성을 계속 추가하거나 둘 다 새 개체에 재정의합니다. 그냥 무시하는 것은 옳지 않습니다. 그리고 그것이 module.exports진짜 보스 라는 것을 명심 하십시오.


exports그리고 module.exports다시 할당하지 않는 한 동일한 exports모듈 내에서.

그것에 대해 생각하는 가장 쉬운 방법은이 줄이 암시 적으로 모든 모듈의 맨 위에 있다고 생각하는 것입니다.

var exports = module.exports = {};

모듈 내 exports에서을 재 할당하면 모듈 내에서 다시 할당하고 더 이상 module.exports. 이것이 함수를 내보내려면 다음을 수행해야하는 이유입니다.

module.exports = function() { ... }

당신은 단순히 당신의 할당 한 경우 function() { ... }에을 exports, 당신은 재 할당 될 것이다 exports에 더 이상 점 module.exports.

module.exports매번 함수를 참조하지 않으려면 다음을 수행 할 수 있습니다.

module.exports = exports = function() { ... }

이것이 module.exports가장 왼쪽의 인수입니다.

속성을에 연결 exports하는 것은 다시 할당하지 않기 때문에 동일하지 않습니다. 이것이 작동하는 이유입니다

exports.foo = function() { ... }

JavaScript는 참조 사본으로 객체를 전달합니다.

객체가 JavaScript에서 참조로 전달되는 방식과 관련하여 미묘한 차이가 있습니다.

exportsmodule.exports같은 객체를 모두 가리 킵니다. exports변수이며 module.exports모듈 객체의 속성입니다.

다음과 같이 씁니다.

exports = {a:1};
module.exports = {b:12};

exports그리고 module.exports지금은 다른 개체를 가리 킵니다. 내보내기를 수정해도 더 이상 module.exports가 수정되지 않습니다.

가져 오기 기능이 검사 module.exports하면{b:12}


몇 가지 테스트를 해보면 nodejs의 모듈 코드 내부에서 다음과 같은 결과를 얻을 수 있습니다.

var module.exports = {};
var exports = module.exports;

그래서:

1:

exports = function(){}; // this will not work! as it make the exports to some other pointer
module.exports = function(){}; // it works! cause finally nodejs make the module.exports to export.

2 :

exports.abc = function(){}; // works!
exports.efg = function(){}; // works!

3 :하지만이 경우에는

module.exports = function(){}; // from now on we have to using module.exports to attach more stuff to exports.
module.exports.a = 'value a'; // works
exports.b = 'value b'; // the b will nerver be seen cause of the first line of code we have do it before (or later)

다음은 Manning 간행물의 액션 북에 있는 node.js의 노드 모듈에 대한 좋은 설명입니다 . 궁극적으로 애플리케이션에서 내보내는 것은 module.exports입니다. exports 는 단순히 module.exports에 대한 전역 참조로 설정 되며 , 처음에는 속성을 추가 할 수있는 빈 개체로 정의됩니다. 그래서 exports.myFunc 단지 속기 module.exports.myFunc . 결과적으로 exports 가 다른 것으로 설정 되면 module.exportsexports 간의 참조끊어집니다 . module.exports 때문에



실제로 내보내지는 것이므로 내보내기 가 더 이상 예상대로 작동하지 않습니다 . 모듈 .exports를 더 이상 참조하지 않습니다 . 해당 링크를 유지하려면 다음과 같이 module.exports 참조 내보내기를 다시 만들 수 있습니다 .

module.exports = exports = db;

나는 몇 가지 테스트를 받았고 이것이 주제에 대해 약간의 빛을 비추어 줄 것이라고 생각합니다.

app.js:

var ...
  , routes = require('./routes')
  ...;
...
console.log('@routes', routes);
...

의 버전 /routes/index.js:

exports = function fn(){}; // outputs "@routes {}"

exports.fn = function fn(){};  // outputs "@routes { fn: [Function: fn] }"

module.exports = function fn(){};  // outputs "@routes function fn(){}"

module.exports.fn = function fn(){};  // outputs "@routes { fn: [Function: fn] }"

새 파일도 추가했습니다.

./routes/index.js:

module.exports = require('./not-index.js');
module.exports = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

"@routes {}"출력이 표시됩니다.


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

"@routes {fn : {}, 사용자 : {}}"출력이 표시됩니다.


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.user = function user(){};

"@routes {user : [Function : user]}"로 변경 user.js하면 { ThisLoadedLast: [Function: ThisLoadedLast] }"@routes {ThisLoadedLast : [Function : ThisLoadedLast]}"출력이 표시됩니다.


하지만 수정하면 ./routes/index.js...

./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.ThisLoadedLast = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.ThisLoadedLast = function ThisLoadedLast(){};

... "@routes {fn : {fn : [Function : fn]}, ThisLoadedLast : {ThisLoadedLast : [Function : ThisLoadedLast]}}")

따라서 항상 module.exports모듈 정의에 사용하는 것이 좋습니다 .

Node 내부에서 무슨 일이 벌어지고 있는지 완전히 이해하지 못하지만 도움이 될 것이라고 확신하므로 더 이해가 되시면 의견을 보내주십시오.

-해피 코딩


이것은 Eloquent JavaScriptrequire() 에서 발췌 한 가장 간단한 형태로 어떻게 작동 하는지 보여줍니다.

문제 모듈이 함수와 같은 내보내기 개체 이외의 값을 직접 내보낼 수 없습니다. 예를 들어, 모듈은 정의하는 객체 유형의 생성자 만 내보낼 수 있습니다. 지금은 require exports가 생성 객체를 내 보낸 값으로 항상 사용하기 때문에 그렇게 할 수 없습니다 .

솔루션 모듈 module에 속성이있는 객체 인 다른 변수를 제공합니다 exports. 이 속성은 처음에는 require에 의해 생성 된 빈 객체를 가리 키지 만 다른 것을 내보내기 위해 다른 값으로 덮어 쓸 수 있습니다.

function require(name) {
  if (name in require.cache)
    return require.cache[name];
  var code = new Function("exports, module", readFile(name));
  var exports = {}, module = {exports: exports};
  code(exports, module);
  require.cache[name] = module.exports;
  return module.exports;
}
require.cache = Object.create(null);

다음은 결과입니다.

console.log("module:");
console.log(module);

console.log("exports:");
console.log(exports);

console.log("module.exports:");
console.log(module.exports);

여기에 이미지 설명 입력

또한:

if(module.exports === exports){
    console.log("YES");
}else{
    console.log("NO");
}

//YES

참고 : CommonJS 사양에서는 공용 멤버를 노출하기 위해 exports 변수를 사용할 수만 있습니다. 따라서 명명 된 내보내기 패턴은 CommonJS 사양과 실제로 호환되는 유일한 패턴입니다. module.exports의 사용은 광범위한 모듈 정의 패턴을 지원하기 위해 Node.js에서 제공하는 확장입니다.


var a = {},md={};

// 첫째, exports 및 module.exports는 동일한 빈 개체를 가리 킵니다.

exp = a;//exports =a;
md.exp = a;//module.exports = a;

exp.attr = "change";

console.log(md.exp);//{attr:"change"}

// exp가 포인트 대신 다른 객체를 가리키면 다른 객체에 대한 속성입니다. md.exp는 비어있는 Object {}입니다.

var a ={},md={};
exp =a;
md.exp =a;

exp = function(){ console.log('Do nothing...'); };

console.log(md.exp); //{}

로부터 문서

exports 변수는 모듈의 파일 수준 범위 내에서 사용할 수 있으며 모듈이 평가되기 전에 module.exports 값이 할당됩니다.

바로 가기를 허용하므로 module.exports.f = ...는 exports.f = ...로 더 간결하게 작성할 수 있습니다. 그러나 다른 변수와 마찬가지로 새 값이 내보내기에 할당되면 더 이상 module.exports에 바인딩되지 않습니다.

module.exports를 가리키는 변수 일뿐입니다.


이 링크가 위의 질문에 답하는 데 유용하다는 것을 알았습니다.

http://timnew.me/blog/2012/04/20/exports-vs-module-exports-in-node-js/

다른 게시물에 추가하려면 노드의 모듈 시스템은

var exports = module.exports 

코드를 실행하기 전에. 따라서 exports = foo를 원할 때 module.exports = exports = foo를 원할 수 있지만 exports.foo = foo 사용하는 것이 좋습니다.


"모듈 내보내기의 루트가 함수 (예 : 생성자)가되기를 원하거나 한 번에 하나의 속성을 빌드하는 대신 하나의 할당으로 전체 객체를 내보내려면 대신 module.exports에 할당하십시오. 수출. " - http://nodejs.org/api/modules.html


1. 내보내기-> 싱글 톤 유틸리티로 사용
2. 모듈 내보내기-> 서비스, 모델 등과 같은 논리적 객체로 사용


두 가지 방법으로 하나의 모듈을 만들어 보겠습니다.

일방 통행

var aa = {
    a: () => {return 'a'},
    b: () => {return 'b'}
}

module.exports = aa;

두 번째 방법

exports.a = () => {return 'a';}
exports.b = () => {return 'b';}

이것이 require () 가 모듈을 통합 하는 방법 입니다.

첫 번째 방법 :

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

    var aa = {
        a: () => {return 'a'},
        b: () => {return 'b'}
    }
    module.exports = aa;

    return module.exports;
}

두 번째 방법

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

    exports.a = () => {return 'a';}
    exports.b = () => {return 'b';}

    return module.exports;
}

둘 다 여기서 사용되는 이유

나는 그들이 단지 명확하게 할 생각이 module.exports, exports그리고 nano동일한 기능을 가리키고 - 당신은 파일 내의 함수를 호출하거나 변수를 사용할 수 있도록. nano함수가 수행하는 작업에 대한 컨텍스트를 제공합니다.

exports수출되지 않을 것입니다 (유일 module.exports하게), 왜 그것을 덮어 쓰는가?

자세한 장단점 은 파일 내에서 exports대신 사용 하는 것과 같은 향후 버그의 위험을 제한 module.exports합니다. 또한 제공하고 설명 한다는 module.exportsexports같은 값을 가리키는 사실에있다.


module.exports vs exports

재할 당하지 module.exports않거나 exports(대신 둘 다 참조하는 객체에 값을 추가 하지 않는 한 ) 문제 exports가 없으며보다 간결하게 사용할 수 있습니다.

둘 중 하나를 비 객체에 할당 할 때 의도적으로 module.exports특정 (예 : 함수)을 원하지 않는 한 혼란 스러울 수있는 다른 위치를 가리 킵니다 .

설정 exports이 아닌 객체로하면 설정해야 겠지만 많은 이해가되지 않습니다 module.exports = exports다른 파일에서 사용할 수 있도록 말을.

let module = { exports: {} };
let exports = module.exports;

exports.msg = 'hi';
console.log(module.exports === exports); // true

exports = 'yo';
console.log(module.exports === exports); // false

exports = module.exports;
console.log(module.exports === exports); // true

module.exports = 'hello';
console.log(module.exports === exports); // false

module.exports = exports;
console.log(module.exports === exports); // true

module.exports함수에 할당 하는 이유는 무엇 입니까?

더 간결하게! 두 번째 예제가 얼마나 짧은 지 비교하십시오.

helloWorld1.js : module.exports.hello = () => console.log('hello world');

app1.js : let sayHello = require('./helloWorld1'); sayHello.hello; // hello world

helloWorld2.js : module.exports = () => console.log('hello world');

app2.js : let sayHello = require('./helloWorld2'); sayHello; // hello world


여기에 이미지 설명 입력

생성하는 각 파일은 모듈입니다. 모듈은 객체입니다. exports : {}기본적으로 빈 객체 인 속성이 있습니다 .

당신은 같은 객체 기능 / 미들웨어를 만들고이 빈 수출에 추가 할 수있는 exports.findById() => { ... }다음 require앱에서 사용 어디서나 ...

controllers / user.js

exports.findById = () => {
    //  do something
}

route.js 에서 다음 을 사용해야합니다.

const {findyId} = './controllers/user'

module.exportsexports모듈 전과 동일한 개체에 두 점을 평가한다.

module.exports객체에 추가 한 모든 속성 require문을 사용하여 다른 모듈에서 모듈을 사용할 때 사용할 수 있습니다 . exports같은 일에 사용할 수있는 바로 가기입니다. 예를 들면 :

module.exports.add = (a, b) => a+b

다음과 같이 작성하는 것과 같습니다.

exports.add = (a, b) => a+b

따라서 exports변수에 새 값을 할당하지 않는 한 괜찮습니다 . 다음과 같이 할 때 :

exports = (a, b) => a+b 

새 값을 할당 exports하면 더 이상 내 보낸 개체에 대한 참조가 없으므로 모듈에 로컬로 유지됩니다.

module.exports사용 가능한 초기 개체에 새 속성을 추가 하는 대신 새 값을 할당하려는 경우 다음과 같이 수행하는 것이 좋습니다.

module.exports = exports = (a, b) => a+b

Node.js 웹 사이트는 이것에 대한 아주 좋은 설명을 가지고 있습니다.


노드 js에서 module.js 파일은 node.load system.every 매번 노드가 파일을 실행할 때 다음과 같이 js 파일 내용을 래핑하는 데 사용됩니다.

'(function (exports, require, module, __filename, __dirname) {',+
     //your js file content
 '\n});'

이 방법은 js 소스 코드 내부의 래핑으로 인해 내보내기, 필수, 모듈 등에 액세스 할 수 있습니다.이 접근 방식은 js 파일에 작성된 기능을 다른 방법으로 가져올 수있는 다른 방법이 없기 때문에 사용됩니다.

그런 다음 노드는 C ++를 사용하여이 래핑 된 함수를 실행합니다. 이때이 함수에 전달 된 내보내기 개체가 채워집니다.

이 함수 매개 변수 내보내기 및 모듈 내부를 볼 수 있습니다. 실제로 exports는 모듈 생성자 함수의 공용 멤버입니다.

다음 코드를보세요

이 코드를 b.js에 복사

console.log("module is "+Object.prototype.toString.call(module));
console.log("object.keys "+Object.keys(module));
console.log(module.exports);
console.log(exports === module.exports);
console.log("exports is "+Object.prototype.toString.call(exports));
console.log('----------------------------------------------');
var foo = require('a.js');
console.log("object.keys of foo: "+Object.keys(foo));
console.log('name is '+ foo);
foo();

이 코드를 a.js에 복사

exports.name = 'hello';
module.exports.name = 'hi';
module.exports.age = 23;
module.exports = function(){console.log('function to module exports')};
//exports = function(){console.log('function to export');}

이제 노드를 사용하여 실행

이것은 출력입니다

module is [object Object]
object.keys id,exports,parent,filename,loaded,children,paths
{}
true

내보내기는 [object Object]입니다.

foo의 object.keys : name is function () {console.log ( 'function to module exports')} function to module exports

이제 a.js에서 주석 처리 된 줄을 제거하고 해당 줄 위의 줄을 주석 처리하고 b.js의 마지막 줄을 제거하고 실행합니다.

자바 스크립트 세계에서는 매개 변수로 전달 된 객체를 재 할당 할 수 없지만 해당 함수의 객체가 다른 함수에 매개 변수로 설정되면 함수의 공용 멤버를 변경할 수 있습니다.

기억하세요

module.exports를 사용하고 require 키워드를 사용할 때 함수를 얻으려는 경우에만 사용하십시오. 위의 예에서 우리는 var foo = require (a.js); foo를 함수로 호출 할 수 있습니다.

이것이 노드 문서에서 "모듈 시스템에 의해 내보내기 객체가 생성됩니다. 때로는 허용되지 않는 경우가 많으며, 많은 사람들이 모듈이 일부 클래스의 인스턴스가되기를 원합니다. 이렇게하려면 원하는 내보내기 객체를 module.exports에 할당합니다."


  1. 모두 module.exportsexports같은 가리킨 function database_module(cfg) {...}.

    1| var a, b;
    2| a = b = function() { console.log("Old"); };
    3|     b = function() { console.log("New"); };
    4|
    5| a(); // "Old"
    6| b(); // "New"
    

    b라인 3에서으로 변경할 수 있으며 a출력은 반대입니다. 결론은 다음과 같습니다.

    ab독립적이다.

  2. 따라서 다음 module.exports = exports = nano = function database_module(cfg) {...}과 같습니다.

    var f = function database_module(cfg) {...};
    module.exports = f;
    exports = f;
    

    상기 가정 module.js에 의해 요구되는, foo.js. 의 이점은 module.exports = exports = nano = function database_module(cfg) {...}다음과 같습니다.

    • 에서 foo.js, 이후는 module.exports것입니다 require('./module.js'):

      var output = require('./modules.js')();
      
    • In moduls.js: exports대신 사용할 수 있습니다 module.exports.

그래서, 당신은 두 경우 드리겠습니다 exportsmodule.exports같은 일을 가리키는.

참고 URL : https://stackoverflow.com/questions/7137397/module-exports-vs-exports-in-node-js

반응형