我有此Javascript constructor-
function TestEngine() {
this.id='Foo';
}
TestEngine.prototype.fooBar = function() {
this.id='bar';
return true;
}
TestEngine.prototype.start = function() {
this.fooBar();
}
TestEngine.prototype.startMethod = function() {
inter = setInterval(this.start, 200);
}
var test = new TestEngine();
test.startMethod();
给我这个错误 -
Uncaught TypeError: Object [object global] has no method 'fooBar'
我试过console.log
,结果发现,当我打电话this.start
从内部setInterval
, this
指向window
对象。 为什么会这样?
在this
指针可以指向的,这取决于很多方面的事情之一:
- 在构造函数(前面有函数调用
new
) this
指向构造的新创建的实例。 - 当一个函数被调用作为对象的方法(例如
obj.funct()
则this
指针的函数指向的对象的内部。 - 你可以明确地设置什么
this
点通过使用call
, apply
或bind
。 - 如果以上都不是那么的
this
指针指向默认的全局对象。 在浏览器中,这是window
对象。
在你的情况你打电话this.start
内setInterval
。 现在考虑这个虚拟执行setInterval
:
function setInterval(funct, delay) {
// native code
}
理解这一点很重要start
不被称为this.start
。 它被称为funct
。 这就像做这样的事情:
var funct = this.start;
funct();
现在,这两个功能通常会执行相同的,但是有一个小小的问题- this
指针指向全局对象在第二种情况下,同时它指向当前this
第一。
做出一个重要的区别是,我们正在谈论this
里面的指针start
。 考虑:
this.start(); // this inside start points to this
var funct = this.start;
funct(); // this inside funct (start) point to window
这是不是一个错误。 这是JavaScript的工作方式。 当你调用一个函数作为对象的方法(见我的上述第二点)的this
指针的功能指向对象内。
在第二种情况下,因为funct
不被称为作为第四规则由缺省应用的对象的方法。 因此, this
指向window
。
您可以通过绑定解决这个问题start
到目前this
指针,然后将它传递给setInterval
,如下所示:
setInterval(this.start.bind(this), 200);
而已。 希望这有助于解释你了解多一点关于JavaScript的迷死。
这里是一个整洁的方式做OOP使用javascript:
//Global Namespace:
var MyNamespace = MyNamespace || {};
//Classes:
MyNamespace.MyObject = function () {
this.PublicVar = 'public'; //Public variable
var _privatVar = 'private'; //Private variable
//Public methods:
this.PublicMethod = function () {
}
//Private methods:
function PrivateMethod() {
}
}
//USAGE EXAMPLE:
var myObj = new MyNamespace.MyObject();
myObj.PublicMethod();
你封装你的方法和变量放入一个命名空间/类这种方式,使其更容易使用和维护。
因此,你可以写你这样的代码:
var MyNamespace = MyNamespace || {};
//Class: TestEngine
MyNamespace.TestEngine = function () {
this.ID = null;
var _inter = null;
//Public methods:
this.StartMethod = function (id) {
this.ID = id;
_inter = setInterval(Start, 1000);
}
//Private methods:
function Start() {
FooBar();
console.log(this.ID);
}
function FooBar() {
this.ID = 'bar';
return true;
}
}
//USAGE EXAMPLE:
var testEngine = new MyNamespace.TestEngine();
testEngine.StartMethod('Foo');
console.log(testEngine.ID);
最初,ID被设置为“富” 1秒ID被设置为“杆”后
请注意,所有的变量和封装在TestEngine类中的方法。
试试这个:
function TestEngine() {
this.id='Foo';
}
TestEngine.prototype.fooBar = function() {
this.id='bar';
return true;
}
TestEngine.prototype.start = function() {
this.fooBar();
}
TestEngine.prototype.startMethod = function() {
var self = this;
var inter = setInterval(function() {
self.start();
}, 200);
}
var test = new TestEngine();
test.startMethod();
setInterval
电话start
与窗口上下文功能。 这意味着,当start
被执行, this
里面start
功能点window
对象。 和window对象没有叫任何方法fooBar
与你的错误。
匿名函数的方法:
它是通过一个很好的做法anonymous function
来setInterval
并从中调用你的函数。 如果你的函数利用了这将是有益this
。
我所做的是,创造了一个临时变量self
和分配this
当它指向你的TestEngine实例和调用它self.start()
函数与它。
现在内start
功能, this
将指向你testInstance和一切会正常运行。
绑定的方法:
Bind
会让你的生活更加简单也提高代码的可读性。
TestEngine.prototype.startMethod = function() {
setInterval(this.start.bind(this), 200);
}
文章来源: Unable to access the object using `this`. `this` points to `window` object