1
var Model = function(client, collection) {
  this.client = client;
  this.collection = collection;
};

Model.prototype = {
  constructor: Model,
  getClient: function(callback) {
    this.client.open(callback);
  },
  getCollection: function(callback) {
    var self = this;

    this.getClient(function(error, client) {
      client.collection(self.collection, callback);
    });
  },
  extend: function(key, fn) {
    var self = this;

    this[key] = function() {
      fn.call(self); // A
    };
  }
};

私が達成したいのは、モデルの機能を「拡張」できることです。

var userModel = new Model(client, 'users');
userModel.extend('create', function(data, callback) {
  this.getCollection(function(error, collection) {
    collection.insert(data, { safe: true }, function(error, doc) {
      callback.call(doc);
    });
  });
});

userModel.create({ fullName: 'Thomas Anderson' }, function() {
  console.log(this); // { _id: '123456789012345678901234', fullName: 'Thomas Anderson' }
});

どういうわけか、Aで、パラメーターの受け渡しを行う必要があります。カスタムの「作成」関数(データとコールバック)のパラメーター数は可変です。

これは可能ですか?もしそうなら、どのように?

4

4 に答える 4

3

うん!.applyメソッドよりもメソッドを使用したい.call。どちらもコンテキストを適用しますが、.applyメソッドは引数の配列、または引数コレクション自体を取ります。

extend: function(key, fn) {
    var self = this;

    this[key] = function() {
      fn.apply(self,arguments); // the special arguments variable is array-like
    };
  }
于 2012-10-08T20:47:04.877 に答える
0
 this[key] = function() {
      fn.apply(self, arguments);
    };
于 2012-10-08T20:48:57.873 に答える
0

@zetlenコメントの後にもう1つ、関数のスコープ(this)は、関数呼び出しの最後のドットの背後にあるものです。この場合は、次のようになります。

userModel.create();

関数の「this」変数は「userModel」になります。

「modelname.functionName()」で呼び出す限り、自分自身を渡す必要はありません。

extend: function(key, f) {
    this[key] = f;
}

(あるいは単に)

userModel.someMethod = function() { ... };

次に、modelkeyを呼び出すときに、引数を関数に直接渡し、必要なスコープを取得します。

var userModel = new Model(...);
userModel.extend('hi', function(arg) {
  this === userModel;
  arg === 42;
});
userModel.hi(42);

このフィドルを見てください:http://jsfiddle.net/NcLQB/1/

ただし、モデルの機能を削除するとスコープがなくなることを覚えておいてください。これを行う場合は、スニペットのように実行し続ける方がよいでしょう。

var funct = userModel.hi;
funct(); // this === global!!!

// OR

// When the event is fired the scope isn't userModel
otherThing.on('someEvent', userModel.hi);
于 2012-10-08T21:02:14.443 に答える
0

プロトタイプでメソッドを作成してスコープを適用する理由が隠されていない限り、extend代わりに作成されたインスタンスにメソッドを割り当てることができます。

var userModel = new Model(client, 'users');
userModel.create = function(data, callback) {
  this.getCollection(function(error, collection) {
    collection.insert(data, { safe: true }, function(error, doc) {
      callback.call(doc);
    });
  });
});

より速く、よりクリーンになり、別の関数を介して引数を渡すことを心配する必要はありません。

言語のダイナミクスを制限しているため、スコープ(またはコンテキスト)をカプセル化して強制することは必ずしも良いことではありません。

于 2012-10-08T21:08:50.597 に答える