无法访问使用`this`的对象。 `this`指向`window`对象(Unable to ac

2019-07-21 23:27发布

我有此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从内部setIntervalthis指向window对象。 为什么会这样?

Answer 1:

this指针可以指向的,这取决于很多方面的事情之一:

  1. 在构造函数(前面有函数调用newthis指向构造的新创建的实例。
  2. 当一个函数被调用作为对象的方法(例如obj.funct()this指针的函数指向的对象的内部。
  3. 你可以明确地设置什么this点通过使用callapplybind
  4. 如果以上都不是那么的this指针指向默认的全局对象。 在浏览器中,这是window对象。

在你的情况你打电话this.startsetInterval 。 现在考虑这个虚拟执行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的迷死。



Answer 2:

这里是一个整洁的方式做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类中的方法。



Answer 3:

试试这个:

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 functionsetInterval并从中调用你的函数。 如果你的函数利用了这将是有益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