更新された回答:
以下のコメントから、うまくいくはずの私の声明に返信してthis.log()ください:
まあ、それが事です。私が子のテスト関数にいるときthisは空のオブジェクトなので、適切なスコープを取得していない行のどこかを想定しています。
をどのように呼び出しているかは示されていませんがtest、そこに問題があると思われます。インスタンス経由で呼び出すChild場合:
var c = new Child();
c.test();
...その後、呼び出し内で子インスタンスになり、そのプロパティを持つオブジェクトをthis(間接的に) 継承します。Parent.prototypelog
でも、呼び方が大事。たとえば、これは機能しません。
var c = new Child();
var f = c.test;
f();
これを行うと、関数の呼び出し内で、インスタンスではなくthisグローバル オブジェクトになります (またはundefined厳密モードの場合) Child。これは、JavaScript では、this主に関数の呼び出し方法によって設定され、そのように呼び出しても目的の設定thisにならないためです。
c.testコールバックとして渡すため、これはコールバックにとって重要です。
someFunctionThatUsesACallback(c.test);
...コールバックするコードが設定されないことを意味thisします。
それを行う必要がある場合は、次のFunction#bindことが役立ちます。
var f = c.test.bind(c); // Returns a version of c.test that, when called,
// will have `this` set to `c`
f(); // Works, `this` is the `Child` instance
同様に:
someFunctionThatUsesACallback(c.test.bind(c));
詳細 (私のブログ):
元の回答:
プロトタイプ階層を正しく設定し、それChild.prototypeを持っlogていない (そしてlogインスタンスにプロパティを設定していない) 場合は、問題なく使用できるはずですthis.log();。できない場合は、階層が正しく設定されていません。
何が機能するのかわかりませんがutil.inherits、 と の関係ChildをParent正しく設定することは複雑ではありません。
function Parent() {
}
Parent.prototype.log = function() {
console.log("log called");
};
function Child () {
Parent.call(this);
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // This line is largely optional, but a good idea
// Usage
var c = new Child();
c.log(); // "log called"
しかし、プロパティをインスタンスにオーバーライドlogしChild.prototypeたり割り当てたりして、のバージョンのlogを使用したい場合は、プロパティがもう参照されないため、そのまま使用することはできません。Parentlogthis.log()Parent.prototype.log
何かの親バージョンを呼び出す必要がある場合 (私はそれらを「スーパーコール」と呼んでいますが、それはオリジナルではないと思います)、さらに多くの作業を行う必要があります。
私は通常、子を構築するために使用する関数に親コンストラクターを渡すことにより、このような階層を設定します。
var Child = (function(Super) {
var pp = Super.prototype;
function Child() {
}
Child.prototype = Object.create(pp);
Child.prototype.doSomething = function() {
// Call `log` with appropriate `this`
pp.log.call(this);
};
return Child;
})(Parent);
常にそのパターンを使用することで、コードParent内に記述する必要がなくなります (代わりに arg を使用します)。そのため、 rebase が必要な場合は、関数に渡すものを変更するだけです。ChildSuperChild
これはかなり醜い (たとえば、 が一番下にあるため、 からChild派生したものであることが一番上では不明確です) し、ボイラープレート コードが含まれているので、毎回書き直す必要はないと思います。そのための簡単なヘルパー スクリプトを作成しました。を呼び出すと、次のようになります。ParentParentLineage
var Child = Lineage.define(Parent, function(p, pp) {
p.doSomething = function() {
// Call `log` with appropriate `this`
pp.log.call(this);
};
});
とプロトタイプLineageの両方を引数として渡すことに注意してください。これにより、それらを簡潔に使用できます (そして、これらの引数名を選択できるため、自分に合った用語を使用できます — 私は作成中の「クラス」のプロトタイプに使用します [上記の]、および親のプロトタイプなど)。ChildParentpChildpp