我认为您正在寻找的是:
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);
要访问constructor.name,您需要使用function name()
语法而不是var name = function()
语法来声明函数。
要保留私有变量并公开公共 api,请将公共变量作为this
函数中的属性公开。
确保this
从构造函数返回以使其工作。
对类名(TestObj 是其中之一)遵循 CamelCase 的命名约定和对变量/方法/对象/等遵循 lowerCamelCase 的命名约定也是一种很好的做法。有助于清楚哪些变量是实例,哪些是类。
测试并查看此处预期的控制台输出。
笔记
关于v.callMeLaterTestObj()
在 setTimeout 的闭包中包装,这种技术是完全跨浏览器兼容的。你不会有任何问题。
该bind
方法较新,尽管有许多库会在较旧的浏览器中为您填充该方法。我个人最喜欢的是下划线。
笔记2
您不能在 setTimeout 中调用对象上的方法而不将其包装在某个地方的闭包中,但是如果您愿意,您可以在不使用泛型bind
函数(如 Underscore 或 jQuery 等提供)的情况下抽象 Class 中的闭包,您可以像这样在类中“滚动你自己的”:
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
方法的闭包来 'reset' this
。
注3
如果您想拥有自己的绑定方法,并且不包含为您提供它或将其包含在每个类中的库,那么您可以使用 Underscore 中的这个,它遵循较新浏览器中的本机方法:
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);
}
这适用于所有浏览器。