JavaScript - “this”的所有者

IT技术 javascript class methods this console.log
2021-02-07 10:58:44

我遵循了创建 JavaScript 秒表教程,并尝试将其扩展为使用多个秒表(一个类的多个实例)。我遇到的问题是,当我试图在时钟滴答作响时显示当前值时,我需要对类实例进行硬编码,因为使用“this”不起作用(在我使用 console.log 的那一行)。我已将代码减少到最低限度以尝试理解这方面,并粘贴了以下内容:

function Timer(){
    var time1 = null;
    var time2 = null;
    var timeLoop = null;

    function getTime(){
        var day = new Date();
        return day.getTime();
    }

    this.start = function(){
        time1 = getTime();

        timeLoop = setInterval(function(){
            time2 = getTime();
            console.log(_Timer.duration());
            //console.log(this.duration());
        },500);
    }

    this.duration = function(){
        return (time1 - time2) / 1000;
    }

}       

我认为下面的链接描述了我的问题,但我对它的理解还不足以在这里应用它。问题是由于所有者是 this.start 而不仅仅是 this,我该如何修改代码以使其适用于任何 Timer 实例?

http://www.quirksmode.org/js/this.html

我已经包含了硬编码值行和不起作用的“这个”行。

谢谢,

杰兰特

6个回答

如果你想让this属性保持一致,你应该绑定正在调用的函数。

例如,

setInterval(function() { /* code here */ }.bind(this), 500)

这样,this内部函数的 将与外部函数的相同。

每当您看到时,function您都可以假设this更改的值,因此间隔的回调函数内部this实际上是window,而不是对象。

简单的解决方案是只存储this在一个变量中

function Timer(){
    var time1 = null;
    var time2 = null;
    var timeLoop = null;

    function getTime(){
        var day = new Date();
        return day.getTime();
    }

    this.start = function(){

        var self = this;

        time1 = getTime();

        timeLoop = setInterval(function(){
            time2 = getTime();
            console.log(self.duration());
        },500);
    }

    this.duration = function(){
        return (time1 - time2) / 1000;
    }

}    

this不是局部变量,所以它不会保存在闭包中。您需要分配一个局部变量:

this.start = function(){
    var self = this;
    time1 = getTime();

    timeLoop = setInterval(function(){
        time2 = getTime();
        console.log(self.duration());
    },500);
}

尝试:

function Timer(){
    var time1 = null;
    var time2 = null;
    var timeLoop = null;
    var _this = this;

    function getTime(){
        var day = new Date();
        return day.getTime();
    }

    this.start = function(){
        time1 = getTime();

        timeLoop = setInterval(function(){
            time2 = getTime();
            console.log(_this.duration());
        },500);
    }

    this.duration = function(){
        return (time1 - time2) / 1000;
    }

}       

先说第一件事。Javascript 不支持基于类的 OOP。它的 OOP 及其继承是原型。

以下是如何使用计时器示例实现原型 OOP 功能的示例:

function Timer(){
  var time1 = null;
  var time2 = null;
  var timeLoop = null;
}

Timer.prototype.getTime = function(){
    var day = new Date();
    return day.getTime();
}

Timer.prototype.start = function(){
    time1 = this.getTime();
    timeLoop = this.setInterval(function(){
        time2 = this.getTime();
        console.log(this.duration());
    }.bind(this),500);
}

Timer.prototype.duration = function(){
    return (time1 - time2) / 1000;
}

查看MDN 的 Javscript Reintroduction的 Custom Objects 部分

它在您的教程中显示的方式没有任何问题。只是这是一种更简洁的方式,并且bind只需要调用该console.log语句,否则语句将关联thiswindow. 如果你摆脱它,你也可以摆脱它bind