简体   繁体   English

Javascript类成员函数通过setInterval调用成员函数,无法访问成员变量

[英]Javascript class member function calling member function by setInterval, couldn't access member variable

I'm trying to make a simple task queue with setInterval with a linked-list. 我正在尝试使用带有链表的setInterval创建一个简单的任务队列。 I created a class with linkedlist and a setInterval function will keep calling a member function to consume the job. 我创建了一个带有链表的类,并且setInterval函数将继续调用成员函数来使用该作业。

 function job_queue(){ this.job = null; this.pointer = this.job; this.job_dispatcher = null; this.length = 0; } job_queue.prototype.add_job = function( job ){ if( this.job == null ){ console.log('1st'); this.job = { job:job, next:null }; this.pointer = this.job; this.length = 1; }else{ console.log('2nd'); this.pointer.next = { job:job, next:null }; this.pointer = this.pointer.next; this.length++; } }; job_queue.prototype.event_handler = function(){ if( typeof this.job['job'] == 'undefined'){ console.log('??'); } if( this.job.job != null ){ console.log('hi'); this.job.job(); this.job = this.job.next(); } } job_queue.prototype.start_dispatch = function(){ if( this.job_dispatcher == null ){ console.log( this.event_handler ); this.job_dispatcher = setInterval( this.event_handler,1000); } } var jq = new job_queue(); function a(){ console.log('hi'); }; function b(){ console.log('hi2'); } jq.add_job(a); jq.add_job(b); jq.add_job(a); jq.start_dispatch(); 

However, when the event_handler function gets called , the program crashes with the log 但是,当调用event_handler函数时,程序会与日志崩溃

 if( typeof this.job['job'] == 'undefined'){

It seems like it can not access the member variable by calling member function with setInterval. 看起来它无法通过使用setInterval调用成员函数来访问成员变量。 I would like to ask what exactly happened with these lines of code and how can I achieve the goal? 我想问一下这些代码行究竟发生了什么,我怎样才能达到目标?

As others have pointed out, setInterval() calls your function in a different context. 正如其他人所指出的, setInterval()在不同的上下文中调用您的函数。 This means that the value of this within the function passed to setInterval() (in this case, event_handler() ) will not be pointing to the correct object. 这意味着传递给setInterval()的函数中的this值(在本例中为event_handler() )将不会指向正确的对象。

A great solution to this problem is JavaScript's bind function : 这个问题的一个很好的解决方案是JavaScript的bind功能

this.job_dispatcher = setInterval(this.event_handler.bind(this), 1000);

setInterval() doesn't work with this . setInterval()不适用this See here: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval#The_this_problem 请参阅: https//developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval#The_this_problem

Code executed by setInterval() is run in a separate execution context to the function from which it was called. setInterval()执行的代码在一个单独的执行上下文中运行,该函数从中调用它。 As a consequence, the this keyword for the called function will be set to the window (or global) object, it will not be the same as the this value for the function that called setTimeout. 因此,被调用函数的this关键字将被设置为窗口(或全局)对象,它将与调用setTimeout的函数的this值不同。

You can call your method inside an anonymous function like this: 您可以在匿名函数中调用您的方法,如下所示:

 function job_queue(){ this.job = null; this.pointer = this.job; this.job_dispatcher = null; this.length = 0; } job_queue.prototype.add_job = function( job ){ if( this.job == null ){ console.log('1st'); this.job = { job:job, next:null }; this.pointer = this.job; this.length = 1; }else{ console.log('2nd'); this.pointer.next = { job:job, next:null }; this.pointer = this.pointer.next; this.length++; } }; job_queue.prototype.event_handler = function(){ if( typeof this.job['job'] == 'undefined'){ console.log('??'); } if( this.job.job != null ){ console.log('hi'); this.job.job(); this.job = this.job.next(); } } job_queue.prototype.start_dispatch = function(){ var self = this; if( this.job_dispatcher == null ){ console.log( this.event_handler ); this.job_dispatcher = setInterval( function(){self.event_handler()},1000); } } var jq = new job_queue(); function a(){ console.log('hi'); }; function b(){ console.log('hi2'); } jq.add_job(a); jq.add_job(b); jq.add_job(a); jq.start_dispatch(); 

If you console.log(this) in the event_handler , you'll see that this points to the Window object . 如果您console.log(this)event_handler ,你会看到this指向Window对象 This is because it is being called in setInterval . 这是因为它在setInterval被调用。

job_queue.prototype.event_handler = function(){
        console.log(this); // <--- A Window object
        if( typeof this.job['job'] == 'undefined'){
            console.log('??');
        }
        if( this.job.job != null ){
            console.log('hi');
            this.job.job();
            this.job = this.job.next();
        }
}

One workaround for it would be to store the job_queue reference as self , and then call setInterval as follows: 一种解决方法是将job_queue引用存储为self ,然后调用setInterval ,如下所示:

var self = this;
this.job_dispatcher = setInterval(function() {
     self.event_handler();
}, 1000);

Code snippet: 代码段:

 function job_queue(){ this.job = null; this.pointer = this.job; this.job_dispatcher = null; this.length = 0; } job_queue.prototype.add_job = function( job ){ if( this.job == null ){ console.log('1st'); this.job = { job:job, next:null }; this.pointer = this.job; this.length = 1; }else{ console.log('2nd'); this.pointer.next = { job:job, next:null }; this.pointer = this.pointer.next; this.length++; } }; job_queue.prototype.event_handler = function(){ console.log(this); if( typeof this.job['job'] == 'undefined'){ console.log('??'); } if( this.job.job != null ){ console.log('hi'); this.job.job(); this.job = this.job.next(); } } job_queue.prototype.start_dispatch = function(){ if( this.job_dispatcher == null ){ console.log( this.event_handler ); var self = this; this.job_dispatcher = setInterval(function() { self.event_handler(self); },1000); } } var jq = new job_queue(); function a(){ console.log('hi'); }; function b(){ console.log('hi2'); } jq.add_job(a); jq.add_job(b); jq.add_job(a); jq.start_dispatch(); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM