2012-02-14 21 views
26

NodeJSアプリケーションを構築するためのモジュールを作成したいのですが、少し失われていますが、検索に時間がかかりませんでした。 。理想的にはNodeJSモジュールの構造化 - 変数とメソッド

var newUser = new User(); 

、私はの上で私のモジュールを必要とするだろう:

は、私のようなものを使用して私のコードでは、新規ユーザーを作成することができ、そこから、私は「ユーザー」モジュールを作成したいと言います私のコードは次のようなものを使用しています:

var User = require('../lib/user'); 

これは素晴らしいです。質問は、私はどのようにユーザーモジュールを構成すべきですか?次は最善の方法ですか?

module.exports = function User() { 
    var authorized = false; 
    var username = undefined; 
    var password = undefined; 
    var statistics = undefined; 

    this.authorized = function() { 
     return authorized; 
    } 
    this.username = function() { 
     return username; 
    } 
    this.statistics = function() { 
     return statistics; 
    } 
} 

私は様々なモジュール変数のゲッターとセッターを書いているので、他のコードから誤ってアクセスしたくないものを隠すことができます。しかし、私は前にこのようにしています。

function User() { 
    this.authStatus = false; 
    this.email; 
    this.displayName; 
    this.inSession; 
} 

User.prototype.isAuthenticated = function() { 
    return(this.authStatus && this.email && this.displayName) 
} 

User.prototype.isInSession = function() { 
    return(this.inSession && this.isAuthenticated()); 
} 

exports.User = User; 

これは1つの警告でも動作します。閉鎖内からユーザープロパティにアクセスする方法が見つかりませんでした。私の理解が正しい場合、2番目の実装では、私はできません。つまり、ユーザーのプロパティを編集するコールバックとして関数をDBライブラリに渡す必要がある場合は、できません。 「この」キーワードは閉鎖ではなく、ユーザーの範囲内であるので、私の理解へのコードは動作しません

User.prototype.login = function() { 
    db.doDbStuff('get user data query', function(_error, _result) { 
     this.username = _result[0].name; //this code will not work 
    }); 
} 

、:それは次のようになりたいです。コードがユーザー関数内に配置されていても、

function User() { 
    this.login = function() { //you know 

これは機能しません。

私の質問は、この問題の最良の解決策は何ですか?それは私が最初のコードブロックで示した方法ですか?それはむしろ面倒で扱いにくく、可変の衝突になりやすいようです。怖いです。

ありがとうございます!あなたが使用

+2

これのいずれかが意味を成さなかった場合、私は事前に謝罪、私はちょうど私の知恵歯のためのいくつかの痛みの薬を取って、私はちょっと軽いとファンキーな感じ。 –

+1

一般的にnode.jsを使うのではなく、javascriptアーキテクチャの領域にもっと溢れ出てくるようです。 http://speakerdeck.com/u/addyosmani/p/scaling-your-javascript-applicationsとhttp://www.slideshare.net/SlexAxton/superclassy-inheritance-in-javascriptはかなり良いです。 – balupton

+0

両方の例で変数はプライベートではないことに注意してください。あなたは見てみるべきです:http://javascript.crockford.com/private.html –

答えて

24

私は、典型的にはプロトタイプに関数を取り付けるという第2のアプローチを採用しています。

「クロージャでは使用できません」という変数の問題は、プロトタイプとは関係ありません。あなたはそれを構造化するどちらの方法でも同じ問題を抱えています。

それはjavascriptののOFT-混乱ダイナミックthisを行うことです:あなたはまた、機能を使用するオプションを持っている

User.prototype.login = function() { 
    var self = this // bind this to self so you have a reference to what `this` was 

    db.doDbStuff('get user data query', function(_error, _result) { 
     self.username = _result[0].name; // self refers to the original `this`, so this works. 
    }); 
} 

http://robotlolita.me/2011/10/09/understanding-javascript-oop.html#sec-2-1

基本的に、あなたは次のように何かをする必要があります。バインド:バインドされた関数内でhttps://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

thisの値は、あなたが.bind(value)に提供するどのような値になります:

あなたが function.bindまたは self = thisやや個人的な味の質問のですが、私たちがやっていたを使用するかどうか
User.prototype.login = function() { 
    db.doDbStuff('get user data query', (function(_error, _result) { 
     this.username = _result[0].name; // bind fixes the original `this`, so this also works. 
    }).bind(this)); 
} 

他の日のfreenode#nodejsのベンチマークでbind()が発見されたのは、var self = thisより20倍遅いです。

モジュールをどのように構成するかについての最初の質問には、githubから学ぶべき例がたくさんあります。好きなモジュールを見つけて、モジュールの構造を調べるだけです。多くの人がコンストラクタを直接公開するよりも工場を好むように思えます(たとえばrequire('module').create())。あなたの電話。

+1

ああ。それはとても華麗でシンプルです! Jeeze。 - ありがとう! –

+0

これは、予期せず変更されたとき、これは本当に混乱しますが、実際に目的に応じて使用するときにはJavascriptの最も強力な機能の1つです。 – timoxley

+0

ええ、Javascriptは私にこの非常に奇妙な雰囲気をもたらします。非常にパワフルで素晴らしいものは「オハイオ州の私の神、これはばかげています。 - プロトタイプメソッドを使用してメンバーを非公開にすることをお勧めする方法はありますか? –

2
User.prototype.login = function() { 
    var _this = this; 
    db.doDbStuff('get user data query', function(_error, _result) { 
     _this.username = _result[0].name; //this code will now work 
    }); 
} 

'this'それがコールバック'this'た、その範囲外でした。

12

別のアプローチとして、私は次のパターンのファンです。

 
module.exports = function User(data) { 

    //this properly private stuff. 

    var privateVar; 
    var username = data.username; 
    var pass = data.pass; //etc 

    function privateFunc() { 
    } 

    return { 
     login: function(cb) { 
      db.doStuff(username, pass, cb); 
     } 
    }; 
}; 
+4

私もこれが好きです。しかし、このアプローチはシングルトンでのみ有効です。このようにインスタンス化することはできません。 – owzim

+2

@owzimこのパターンは、実際にはシングルトンだけでなく、module.exports =(function(){...})()とよく似ています。これは関数を直ちに実行するため、単一のパターンです。しかし、あなたは今require( 'data')(my_instance_data).myInstanceFunction()を実行できるので、この答えのコードはシングルトンではありません。 – Vegard

関連する問題