私はあなたが探しているのはこれだと思います:
function TestObj(value) {
var _value = value;
this.giveMe = function() {
return _value;
};
this.callMeLaterTestObj = function() {
console.log('I am ' + this.constructor.name + ' my value is ' + _value);
};
return this;
};
function callMeLater(v, i) {
setTimeout(function() {
v.callMeLaterTestObj();
}, 10);
}
var v1 = new TestObj(1);
var v2 = new TestObj(2);
var v3 = new TestObj(3);
console.log('V1= ' + v1.giveMe());
console.log('V2= ' + v2.giveMe());
console.log('V3= ' + v3.giveMe());
console.log('---');
callMeLater(v1, 1);
callMeLater(v2, 2);
callMeLater(v3, 3);
function name()
Constructor.nameにアクセスするには、構文ではなく構文を使用して関数を宣言する必要がありvar name = function()
ます。
プライベート変数を保持し、パブリックAPIを公開するにthis
は、関数内のプロパティとしてパブリック変数を公開します。
this
必ずコンストラクター関数から戻って動作させてください。
また、クラス名(TestObjが1つ)の場合はCamelCaseの命名規則に従い、変数/メソッド/オブジェクトなどの場合はlowerCamelCaseの命名規則に従うことをお勧めします。どの変数がインスタンスで、どの変数がクラスであるかを明確に保つのに役立ちます。
ここで期待されるコンソール出力をテストして確認します。
ノート
setTimeoutのクロージャーでのラップに関してv.callMeLaterTestObj()
、この手法は完全にクロスブラウザー互換です。問題はありません。
このbind
方法は新しいものですが、古いブラウザでそれをシムするライブラリはたくさんあります。私の個人的なお気に入りはアンダースコアです。
注2
どこかでクロージャにラップせずにsetTimeoutでオブジェクトのメソッドを呼び出すことはできませんが、必要に応じて、ジェネリックbind
関数(UnderscoreやjQueryなどによって提供される)を使用せずにクラスのクロージャを抽象化できます。次のようなクラスで「自分でロール」します。
function TestObj(value) {
var _value = value;
var _self = this;
this.giveMe = function() {
return _value;
};
this.callMeLaterTestObj = function() {
console.log('I am ' + this.constructor.name + ' my value is ' + _value);
};
this.getBinding = function(method) {
var _self = this;
return function() {
_self[method].apply(_self, arguments);
};
};
return this;
};
function callMeLater(v, i) {
setTimeout(v.getBinding('callMeLaterTestObj'), 10);
}
var v1 = new TestObj(1);
var v2 = new TestObj(2);
var v3 = new TestObj(3);
console.log('V1= ' + v1.giveMe());
console.log('V2= ' + v2.giveMe());
console.log('V3= ' + v3.giveMe());
console.log('---');
callMeLater(v1, 1);
callMeLater(v2, 2);
callMeLater(v3, 3);
説明:
メソッドをに渡すときは参照によって渡すため、何らかのバインディングを使用する必要がありsetTimeout
ます。したがって、setTimeoutが認識するのは関数であり、それが存在していたオブジェクトではありません。そのため、のコンテキストが失われますthis
。
したがって、setTimeoutはデフォルトのスコープ(つまりブラウザウィンドウ)で関数を実行するためthis
、インライン匿名関数を介して、またはapply
メソッドを使用して「リセット」するクロージャを返すことにより、参照によって戻る方法が必要this
です。
注3
独自のバインドメソッドが必要で、それを提供するライブラリを含めたり、すべてのクラスに含めたりしたくない場合は、アンダースコアからこれを使用できます。これは、新しいブラウザのネイティブメソッドに従います。
function bind(func, context) {
var bound, args;
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError;
args = slice.call(arguments, 2);
return bound = function() {
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
ctor.prototype = func.prototype;
var self = new ctor;
var result = func.apply(self, args.concat(slice.call(arguments)));
if (Object(result) === result) return result;
return self;
};
};
次に、次のように使用します。
function callMeLater(v, i) {
setTimeout(bind(v.callMeLaterTestObj, v), 10);
}
これはすべてのブラウザでうまく機能します。