javascript - 모듈이란 - node.js 변수




Node.js module.exports의 목적은 무엇이며 어떻게 사용합니까? (8)

모듈 시스템의 목적은 무엇입니까?

다음과 같은 작업을 수행합니다.

  1. 우리의 파일 을 정말 큰 크기로 유지 합니다. 예를 들어 5000 줄의 코드가있는 파일을 개발하는 동안 대개 다루기가 정말 어렵습니다.
  2. 우려의 분리를 강요합니다. 코드를 여러 파일로 분리하면 모든 파일에 대해 적절한 파일 이름을 가질 수 있습니다. 이렇게하면 모든 모듈이 무엇을하는지, 어디에서 찾을 수 있는지 쉽게 식별 할 수 있습니다 (우리는 여전히 당신의 책임하에 논리적 디렉토리 구조를 만들었다 고 가정).

모듈을 사용하면 코드의 특정 부분을 쉽게 찾을 수 있으므로 코드를 유지 관리 할 수 ​​있습니다.

어떻게 작동합니까?

NodejS 는 다음과 같은 방식으로 작동하는 CommomJS 모듈 시스템을 사용합니다.

  1. 파일이 뭔가를 내보내 module.export 하면 module.export 구문을 사용하여 선언해야합니다.
  2. 파일이 뭔가를 가져오고 싶다면 require('file') 구문을 사용하여 선언해야합니다.

예:

test1.js

const test2 = require('./test2');    // returns the module.exports object of a file

test2.Func1(); // logs func1
test2.Func2(); // logs func2

test2.js

module.exports.Func1 = () => {console.log('func1')};

exports.Func2 = () => {console.log('func2')};

알아두면 유용한 다른 것들 :

  1. 모듈이 캐싱되고 있습니다. 동일한 모듈을 2 개의 다른 파일에로드 할 때 모듈은 한 번만로드하면됩니다. 두 번째로 require() 가 캐시에서 가져온 동일한 모듈에서 호출됩니다.
  2. 모듈은 동기식으로로드됩니다 . 비동기 적으로 require() 에서 검색 한 객체에 즉시 액세스 할 수없는 경우이 동작이 필요합니다.

Node.js module.exports의 목적은 무엇이며 어떻게 사용합니까?

이것에 대한 정보를 찾을 수없는 것 같지만 Node.js에서 오히려 중요한 부분 인 것처럼 보입니다. 종종 소스 코드에서 볼 수 있습니다.

Node.js 문서 에 따르면 :

기준 치수

현재 module 대한 참조입니다. 특히 module.exports 는 내보내기 객체와 동일합니다. 자세한 내용은 src/node.js 를 참조하십시오.

그러나 이것은 실제로 도움이되지 않습니다.

module.exports 는 정확히 무엇을합니까? 간단한 예제는 무엇입니까?


NodeJS 모듈 메커니즘은 RequireJS 뿐만 아니라 SproutCore , CouchDB , Wakanda , OrientDB , ArangoDB , RingoJS , TeaJS , SilkJS , curl.js 또는 Adobe Photoshop ( PSLib 통해)과 같은 많은 다른 구현에서 지원되는 CommonJS 모듈을 기반으로합니다. ). here 에는 알려진 구현의 전체 목록이 here .

모듈에서 노드 특정 기능 또는 모듈을 사용 하지 않는 한, CommonJS 표준의 일부가 아닌 module.exports 대신 exports 를 사용하고 다른 구현에서는 대부분 지원되지 않습니다.

또 다른 NodeJS 고유 기능은이 스레드에서 Jed Watson이 제공 한 마지막 예제 에서처럼 속성 및 메서드를 추가하는 대신 exports 할 새 객체에 대한 참조를 할당하는 경우입니다. CommonJS 모듈 메커니즘 의 순환 참조 지원중단되므로 개인적으로이 방법을 권장하지 않습니다. 그런 다음 모든 구현에서 지원되지 않으며보다 일반적인 모듈을 제공하기 위해 Jed 예제를 다음과 같이 작성해야합니다.

(sayhello.js) :

exports.run = function() {
    console.log("Hello World!");
}

(app.js) :

var sayHello = require('./sayhello');
sayHello.run(); // "Hello World!"

또는 ES6 기능 사용

(sayhello.js) :

Object.assign(exports, {
    // Put all your public API here
    sayhello() {
        console.log("Hello World!");
    }
});

(app.js) :

const { sayHello } = require('./sayhello');
sayHello(); // "Hello World!"

추신 : Appcelerator는 CommonJS 모듈도 구현하지만 원형 참조는 지원하지 않습니다 (참조 : Appcelerator 및 CommonJS 모듈 (캐싱 및 순환 참조) ).


모듈은 관련 코드를 단일 코드 단위로 캡슐화합니다. 모듈을 생성 할 때 이것은 관련된 모든 함수를 하나의 파일로 옮기는 것으로 해석 될 수 있습니다.

두 개의 함수를 포함하는 Hello.js 파일이 있다고 가정합니다.

sayHelloInEnglish = function() {
  return "Hello";
};
sayHelloInSpanish = function() {
  return "Hola";
};

코드의 유틸리티가 둘 이상의 호출 일 때만 함수를 작성합니다.

함수의 유틸리티를 World.js와 같은 다른 파일로 증가 시키려고한다고 가정합니다.이 경우 파일 내보내기는 module.exports에서 얻을 수있는 그림이됩니다.

아래 두 코드를 모두 내보낼 수 있습니다.

var anyVariable={
 sayHelloInEnglish = function() {
      return "Hello";
    };
  sayHelloInSpanish = function() {
      return "Hola";
    }; 
}
module.export=anyVariable;

이제 World.js inorder에 파일 이름을 사용하여 해당 기능을 사용하면됩니다.

var world= require("./hello.js");

새 객체에 대한 참조를 modules.exports 거나 modules.exports 할당하는 경우 몇 가지주의해야합니다.

1. 원래의 exportsmodule.exports 이전에 첨부 된 모든 속성 / 메소드는 물론 내 보낸 객체가 다른 새로운 것을 참조하기 때문에 손실됩니다

이것은 분명하지만 , 기존 모듈의 시작 부분에 내 보낸 메소드를 추가하는 경우, 내 보낸 내 보낸 오브젝트가 끝에 다른 오브젝트를 참조하지 않도록하십시오

exports.method1 = function () {}; // exposed to the original exported object
exports.method2 = function () {}; // exposed to the original exported object

module.exports.method3 = function () {}; // exposed with method1 & method2

var otherAPI = {
    // some properties and/or methods
}

exports = otherAPI; // replace the original API (works also with module.exports)

2. exportsmodule.exports 중 하나가 새로운 값을 참조 할 경우 더 이상 같은 객체를 참조하지 않습니다.

exports = function AConstructor() {}; // override the original exported object
exports.method2 = function () {}; // exposed to the new exported object

// method added to the original exports object which not exposed any more
module.exports.method3 = function () {}; 

3. 까다로운 결과. exportsmodule.exports 모두에 대한 참조를 변경하면 어떤 API가 노출되어 있는지 말하기가 어렵습니다 ( module.exports 이긴 것처럼 보입니다)

// override the original exported object
module.exports = function AConstructor() {};

// try to override the original exported object
// but module.exports will be exposed instead
exports = function AnotherConstructor() {}; 

이것은 이미 답변되었지만 몇 가지 설명을 추가하고 싶었습니다 ...

다음과 module.exports exportsmodule.exports 를 모두 사용하여 응용 프로그램에 코드를 가져올 수 있습니다.

var mycode = require('./path/to/mycode');

ExpressJS 예제 코드에서 볼 수있는 기본 사용 사례는 .js 파일의 exports 객체에 대한 속성을 설정 한 다음 require() 사용하여 가져 오는 것입니다.

따라서 간단한 계산 예에서 다음을 수행 할 수 있습니다.

(counter.js) :

var count = 1;

exports.increment = function() {
    count++;
};

exports.getCount = function() {
    return count;
};

... 그런 다음 애플리케이션 (web.js 또는 다른 모든 .js 파일)에서 다음을 수행하십시오.

var counting = require('./counter.js');

console.log(counting.getCount()); // 1
counting.increment();
console.log(counting.getCount()); // 2

간단히 말해, 필요한 파일을 단일 객체를 반환하는 함수로 생각할 수 있으며, 내보낼 때 반환되는 객체에 속성 (문자열, 숫자, 배열, 함수 등)을 추가 할 수 있습니다.

때로는 require() 호출에서 반환 된 객체가 속성이있는 객체가 아니라 호출 할 수있는 함수가되기를 원할 것입니다. 이 경우 module.exports 도 다음과 같이 설정해야합니다.

(sayhello.js) :

module.exports = exports = function() {
    console.log("Hello World!");
};

(app.js) :

var sayHello = require('./sayhello.js');
sayHello(); // "Hello World!"

이 답변 에서는 수출과 module.exports의 차이점을보다 잘 설명 합니다 .


참조 연결은 다음과 같습니다.

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

함수 또는 변수와 같은 exports 또는 module.exports 의 속성이 외부에 노출됩니다.

좀 더주의를 기울여야하는 것이 override : 수출을 override 하지 마십시오.

왜 ?

module.exports의 참조 만 내보내므로 내보내기에 속성을 추가 할 수 있지만 내보내기를 무시하면 참조 링크가 끊어집니다.

좋은 예 :

exports.name = 'william';

exports.getName = function(){
   console.log(this.name);
}

나쁜 예 :

exports = 'william';

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

다음과 같이 하나의 함수 또는 변수 만 노출하려는 경우

// test.js
var name = 'william';

module.exports = function(){
    console.log(name);
}   

// index.js
var test = require('./test');
test();

이 모듈은 오직 하나의 함수 만 노출 시켰고 이름의 속성은 외부에 대해 private입니다.


module.exportsrequire 호출의 결과로 실제로 반환되는 객체입니다.

exports 변수는 처음에는 같은 객체로 설정됩니다 (즉, "별칭"). 모듈 코드에서 다음과 같이 작성합니다.

var myFunc1 = function() { ... };
var myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;

내부적으로 범위가 지정된 함수 myFunc1myFunc2 를 내보내거나 "노출"합니다.

그리고 호출 코드에서 다음을 사용합니다.

var m = require('./mymodule');
m.myFunc1();

마지막 행은 require 의 결과가 (일반적으로) 속성에 액세스 할 수있는 일반 객체 인 방법을 보여줍니다.

주의 : exports 를 덮어 쓰면 더 이상 module.exports 참조하지 않습니다. 따라서 새 객체 (또는 함수 참조)를 module.exports 객체를 module.exports 할당해야합니다.

exports 객체에 추가 된 이름이 모듈의 내부 범위 이름과 같을 필요가 없다는 점에 유의해야합니다. 따라서 다음과 같이 할 수 있습니다.

var myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required

뒤에 :

var m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName

http, sys 등의 node.js를 다운로드하여 설치할 때 node.js에 기본 또는 기존 모듈이 있습니다.

그들은 이미 node.js에 있기 때문에 우리는이 모듈을 사용하기 위해 기본적으로 import 모듈 을 사용합니다. 왜 그런가? 노드 .js에 이미 있기 때문입니다. 가져 오기는 node.js에서 가져 와서 프로그램에 넣는 것과 같습니다. 그리고 그들을 사용합니다.

내보내기 가 정반대인데 원하는 모듈을 만들고, 모듈 addition.js를 말하고 그 모듈을 node.js에 넣으면 내보내는 것입니다.

여기에 아무것도 쓰지 않기 전에, module.exports.additionTwoexports.additionTwo같습니다.

허, 그게 이유야, 우리는 좋아해.

exports.additionTwo = function(x)
{return x+2;};

경로에주의하십시오.

additional.js 모듈을 생성했다고 가정 해 보겠습니다.

exports.additionTwo = function(x){
return x + 2;
};

NODE.JS 명령 프롬프트에서 이것을 실행하면 다음과 같습니다.

node
var run = require('addition.js');

이것은 말하기 오류 것입니다

오류 : 모듈 addition.js을 (를) 찾을 수 없습니다.

이것은 node.js 프로세스가 경로를 언급하지 않았기 때문에 addition.js를 사용할 수 없기 때문입니다. 따라서 NODE_PATH를 사용하여 경로를 설정할 수 있습니다.

set NODE_PATH = path/to/your/additon.js

이제는 오류없이 성공적으로 실행됩니다 !!

한 가지 더, NODE_PATH를 설정하지 않고 nodejs 명령 프롬프트로 돌아가서 addition.js 파일을 실행할 수도 있습니다.

node
var run = require('./addition.js');

현재 디렉토리에 있다고 말하면서 경로를 제공하기 때문에 ./ 이것은 또한 성공적으로 실행되어야합니다.





node.js