13

私はJavaScriptで関数を作成し、その関数にさらにメソッドと属性を追加できるのが好きです

myInstance = function() {return 5}
myInstance.attr = 10

これらのオブジェクトを生成するクラスを作成したいと思います。Function 基底クラスから継承する必要があると思います。

言い換えれば、私はしたい:

var myInstance = new myFunctionClass()
var x = myInstance()
// x == 5

しかし、myFunctionClass の作成方法がわかりません。次のことを試しましたが、うまくいきません。

var myFunctionClass = function() {Function.call(this, "return 5")}
myFunctionClass.prototype = new Function()
myInstance = new myFunctionClass()
myInstance()
// I would hope this would return 5, but instead I get
// TypeError: Property 'myInstance' of object #<Object> is not a function

ここにあるより複雑な(そしてより適切な?)継承方法も試しました:How to "properly" create a custom object in JavaScript? 、もう運がありません。また、node.js にある util.inherits(myFunctionClass, Function) を使用してみました。まだ運がない

私は Google を使い果たしたので、基本的または明白な何かが欠けているに違いないと感じています。助けていただければ幸いです。

4

3 に答える 3

14

から継承しようとしていFunctionます。これは正しい痛みです。代わりに次のことを行うことをお勧めします

実際の例

var Proto = Object.create(Function.prototype);
Object.extend(Proto, {
  constructor: function (d) {
    console.log("construct, argument : ", d);
    this.d = d; 
    // this is your constructor logic
  },
  call: function () {
    console.log("call", this.d);
    // this get's called when you invoke the "function" that is the instance
    return "from call";
  },
  method: function () {
    console.log("method");
    // some method
    return "return from method";
  },
  // some attr
  attr: 42
});

「クラス」の基礎となるプロトタイプ オブジェクトを作成します。一般的なメソッド/属性があります。また、オブジェクトの構築時に呼び出されるコンストラクターと、関数を呼び出すときに呼び出される call メソッドもあります。

var functionFactory = function (proto) {
  return function () {
    var f = function () {
      return f.call.apply(f, arguments);      
    };
    Object.keys(proto).forEach(function (key) {
      f[key] = proto[key];
    });
    f.constructor.apply(f, arguments);
    return f;
  }
}

関数ファクトリは、プロトタイプ オブジェクトを受け取り、そのファクトリを返します。呼び出されたときに返される関数は、プロトタイプ オブジェクトから「継承」する新しい関数オブジェクトを提供します。

var protoFactory = functionFactory(proto);
var instance = protoFactory();

ここで、ファクトリを作成してからインスタンスを作成します。

ただし、これは適切なプロトタイプ OO ではありません。プロトタイプのプロパティを新しいオブジェクトに浅くコピーしているだけです。そのため、プロトタイプへの変更は元のオブジェクトには反映されません。

真のプロトタイプ OO が必要な場合は、ハックを使用する必要があります。

var f = function () {
  // your logic here
};
f.__proto__ = Proto;

非標準の deprecated をどのように使用しているかに注意してください.__proto__ [[Prototype]]実行時に悪と見なされる値を変更しています。

于 2011-11-02T23:33:08.243 に答える
1

JS では、関数はオブジェクトですが、コンストラクターが関数を返すことはできません。したがって、それ自体が実行可能なプロトタイプをインスタンス化することはできません。(私はこれで正しいですか?そうでない場合は修正してください。興味深い質問です)。

ファクトリ関数を実行できますが:

var makeCoolFunc = function() {
  var f = function() { return 5 };
  f.a = 123;
  f.b = 'hell yes!'
  return f;
};

var func = makeCoolFunc();
var x = func();
于 2011-11-02T23:35:15.447 に答える