Node.js - yapıcı olarak module.exports'un kullanılması


120

Node.js kılavuzuna göre:

Modül dışa aktarımının kökünün bir işlev (bir yapıcı gibi) olmasını istiyorsanız veya bir seferde bir özellik oluşturmak yerine tam bir nesneyi tek bir atamada dışa aktarmak istiyorsanız, bunu export yerine module.exports'a atayın. .

Verilen örnek şudur:

// file: square.js
module.exports = function(width) {
  return {
    area: function() {
      return width * width;
    }
  };
}

ve şu şekilde kullanıldı:

var square = require('./square.js');
var mySquare = square(2);
console.log('The area of my square is ' + mySquare.area());

Sorum: Örnek neden kare olarak nesne kullanmıyor? Aşağıdaki geçerli midir ve örneği daha "nesne yönelimli" yapar mı?

var Square = require('./square.js');
var mySquare = new Square(2);
console.log('The area of my square is ' + mySquare.area());

1
Örneğiniz bir sözdizimi hatası. Adlandırma sonra squareiçin artık mevcut değil. Squarenew square()
Sukima

3
Üzgünüm, bu bir yazım hatasıydı. Onu düzeltti. Niyetim büyük harfle başlayan Nesne / İşlev adını ve küçük harfle başlayan örnek adını göstermekti.
Naresh

4
Ben de öyle düşündüm, bu yüzden cevabımı yazdığım gibi yazdım . Sadece başkalarının da modüllere aynı şekilde bakmasından gerçekten memnun olduğumu söylemek istedim. Sık sık yeni anahtar kelimeyi kullanıyorum ve modüllerimi tek bir yapıcı işlevini dışa aktarmak için düzenliyorum. Çözümlerin okunabilirliğini ve kavramsallaştırılmasını kolaylaştırdığını görüyorum. Ne tür bir yapı kullanmak istediğimi bir bakışta anlayabiliyorum. Benim gibi düşündüğün için şeref;)
Sukima

Yanıtlar:


173

CommonJS modülleri, dışa aktarılan özellikleri tanımlamak için iki yol sağlar. Her iki durumda da bir Nesne / Fonksiyon döndürüyorsunuz. Fonksiyonlar JavaScript'te birinci sınıf vatandaş olduklarından, tıpkı Nesneler gibi hareket edebilirler (teknik olarak Nesnelerdir). Bu, newanahtar kelimeleri kullanma hakkındaki sorunuzun basit bir cevabı olduğunu söyledi: Evet. Göstereceğim ...

Modül dışa aktarımı

exportsÖzellik eklemek için sağlanan değişkeni kullanabilirsiniz . Başka bir modülde gerektiğinde, bu atama özellikleri kullanılabilir hale gelir. Veya module.exports özelliğine bir nesne atayabilirsiniz. Her iki durumda da döndürülen require()şey değerine bir referanstır module.exports.

Bir modülün nasıl tanımlandığına dair sözde kod örneği:

var theModule = {
  exports: {}
};

(function(module, exports, require) {

  // Your module code goes here

})(theModule, theModule.exports, theRequireFunction);

Yukarıdaki örnekte module.exportsve exportsaynı nesnedir. İşin güzel yanı, CommonJS modüllerinizde bunlardan hiçbirini görmemenizdir, çünkü tüm sistem sizin için tüm bilmeniz gereken şey, bir dışa aktarma özelliği olan bir modül nesnesi ve module.exports'un yaptığı aynı şey.

Yapıcılar ile gerektir

Bir işlevi doğrudan module.exportssize ekleyebildiğiniz için , aslında bir işlevi döndürebilirsiniz ve herhangi bir işlev gibi, bir kurucu olarak yönetilebilir (Bu italik olarak yazılmıştır çünkü JavaScript'teki bir işlev ile yapıcı arasındaki tek fark onu nasıl kullanmayı düşündüğünüzdür. hiçbir fark yok.)

Dolayısıyla, aşağıdaki mükemmel bir kod ve ben şahsen onu teşvik ediyorum:

// My module
function MyObject(bar) {
  this.bar = bar;
}

MyObject.prototype.foo = function foo() {
  console.log(this.bar);
};

module.exports = MyObject;

// In another module:
var MyObjectOrSomeCleverName = require("./my_object.js");
var my_obj_instance = new MyObjectOrSomeCleverName("foobar");
my_obj_instance.foo(); // => "foobar"

Yapıcı olmayanlar için gerekli

Aynı şey yapıcı olmayan benzeri işlevler için de geçerlidir:

// My Module
exports.someFunction = function someFunction(msg) {
  console.log(msg);
}

// In another module
var MyModule = require("./my_module.js");
MyModule.someFunction("foobar"); // => "foobar"

2
Kısaca ('./ my-object.js') ("foobar") gerektirebilir miyim? Veya farklı bir kullanım durumu için gerekli ('modül') (parametreler) sözdizimi mi?
Hampus Ahlgren

1
Hiçbir şey sizi durduramaz, hepsi sadece JavaScript. Yani evet, daha kısa sözdizimini kullanabilirsiniz.
Sukima

3
Bir modülün nasıl tanımlandığına dair sözde kod örneği, Node.js modül sistemi hakkındaki anlayışımı tamamen açıklığa kavuşturdu. Teşekkür ederim!
Nitax

130

Kanımca, node.js örneklerinden bazıları oldukça uydurma.

Gerçek dünyada buna benzer bir şey görmeyi bekleyebilirsiniz

// square.js
function Square(width) {

  if (!(this instanceof Square)) {
    return new Square(width);
  }

  this.width = width;
};

Square.prototype.area = function area() {
  return Math.pow(this.width, 2);
};

module.exports = Square;

kullanım

var Square = require("./square");

// you can use `new` keyword
var s = new Square(5);
s.area(); // 25

// or you can skip it!
var s2 = Square(10);
s2.area(); // 100

ES6 kullanıcıları için

class Square {
  constructor(width) {
    this.width = width;
  }
  area() {
    return Math.pow(this.width, 2);
  }
}

export default Square;

ES6'da kullanma

import Square from "./square";
// ...

Bir sınıf kullanırken, gereken kullanmak newbunu instatiate için anahtar kelime. Diğer her şey aynı kalır.


3
Alışılmadık derecede özlü yapı!
Christophe Marois

1
Yani <ES6 örneğinizde kullanmakla kullanmamak arasında bir fark yok gibi görünüyor new. Ama bu sadece o çeke sahip olduğunuz için this instanceof squaremi? Eğer öyleyse, bu mekanizma tam olarak ne yapıyor?
arichards

1
Başkalarına yardımcı olma ihtimaline karşı sorduğum ve aradığım sorular: Nerede importve exporttanımlanmış? Bunlar ECMAScript 6 (ES6) içinde ayrılmış anahtar sözcüklerdir. ES6'dan önce, modülleri yönetmek için kitaplıkları kullanmak gerekiyordu. Düğümün modülasyonu, CommonJS kütüphanesinin Modüllerinden sonra modellenmiştir. Nedir defaultiçinde export default Square? Bu, yalnızca 'dosyayı' içe aktardığınızda neyin içe aktarılacağını belirtir ve o dosyadan diğer belirli dışa aktarmaları değil. Var oldukları sürece, bu sayfaları yararlı buldum: spring.io/understanding/javascript-modules ve exploringjs.com/es6/ch_modules.html
arichards

1

Bu sorunun gerçekten nasıl require()çalıştığıyla hiçbir ilgisi yok . Temel olarak, module.exportsmodülünüzde ayarladığınız her şey , require()çağrıdan geri dönecektir .

Bu şuna eşdeğer olacaktır:

var square = function(width) {
  return {
    area: function() {
      return width * width;
    }
  };
}

newArama yaparken anahtar kelimeye gerek yoktur square. İşlev örneğinin kendisini squaredöndürmüyorsunuz, sonunda yeni bir nesne döndürüyorsunuz. Bu nedenle, bu işlevi doğrudan çağırabilirsiniz.

Daha karmaşık argümanlar için şuna bakın new: JavaScript'in "yeni" anahtar kelimesi zararlı olarak kabul ediliyor mu?


3
Yeni anahtar kelimeyi kullanmakta yanlış bir şey yok. Etrafındaki tüm FUD'den nefret ediyorum.
Sukima

1
@Sukima Kabul. :-D Bu davada neden önemli olmadığına işaret ediyorum ve diğer soruyla bağlantılı olarak neworadaki savaşa başkalarının da katılabilmesi için.
Brad

0

Örnek kod:

esas olarak

square(width,function (data)
{
   console.log(data.squareVal);
});

aşağıdakileri kullanmak işe yarayabilir

exports.square = function(width,callback)
{
     var aa = new Object();
     callback(aa.squareVal = width * width);    
}

0

Sonunda Node, Javascript ile ilgilidir. JS'nin bir şeyi başarmanın birkaç yolu vardır, bir "kurucu" elde etmek için aynı şeydir , önemli olan bir işlevi döndürmektir .

Bu şekilde, örneğin Web Tarayıcısı ortamında JS kullanarak oluşturduğumuz gibi, aslında yeni bir işlev oluşturuyorsunuz.

Şahsen ben, Sukima'nın bu yazıda önerdiği gibi prototip yaklaşımını tercih ediyorum: Node.js - yapıcı olarak module.exports kullanımı

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.