27

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
    });
}

私の理解では、「this」キーワードはユーザーではなくクロージャーのスコープ内にあるため、コードは機能しません。コードが User 関数内に配置されたとしても、次のようになります。

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

それはうまくいきません。

私の質問は、この問題の最善の解決策は何ですか? 最初のコード ブロックで提示した方法ですか? それはかなり面倒で厄介で、変数の衝突が発生しやすいようです。怖いです。

前もって感謝します!

4

3 に答える 3

26

私は通常、関数をプロトタイプにアタッチする 2 番目のアプローチを使用します。

「クロージャーで使用できない」変数で発生している問題は、プロトタイプとは関係ありません。どちらの方法で構成しても同じ問題が発生します。

これは、javascript のしばしば混乱を招くダイナミックと関係があり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.
    });
}

function.bind を使用するオプションもあります: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

バインドされた関数内では、 の値はthisに提供した値になります.bind(value)

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));
}

使用するかどうかfunction.bindself = this個人的な好みの問題ですが、先日 freenode#nodejs でいくつかのベンチマークを行っていたところ、bind()より 20 倍遅いことがわかりましたvar self = this

モジュールを構築する方法に関する最初の質問については、github で学ぶべき例がたくさんあります。お気に入りのモジュールを見つけて、その構造を調べるだけです。多くの人が、コンストラクターを直接公開するよりもファクトリーを好むようです (例: require('module').create())。あなたの電話。

于 2012-02-14T00:49:30.473 に答える
12

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

module.exports = 関数 ユーザー(データ) {

    //これは適切にプライベートなものです。

    var privateVar;
    var ユーザー名 = data.username;
    var pass = data.pass; //等

    関数 privateFunc() {
    }

    戻る {
        ログイン: 関数(cb) {
            db.doStuff(ユーザー名、パス、cb);
        }
    };
};
于 2013-01-25T23:43:17.223 に答える
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'が使用したのはその範囲外でした。それは callbackでした'this'

于 2012-02-14T00:39:43.207 に答える