2012-06-08 2 views
8

Предположим, у меня есть функция а:Как передать «это» в окне setInterval

function a() { 
    this.b = 1; 
    this.set = setInterval(function() {console.log(this.b);}, 200); 
} 

Так что, когда a.set() вызывается анонимная функция будет вызвана. Но это не будет работать так, как это в то время, когда функция запускается, указывает на объект окна. Также не рекомендуется использовать a.b, так как могут быть несколько экземпляров a.

Что такое хорошее решение этой проблемы?

+0

Почему вы не используете 'apply' или' call' https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply – Deeptechtons

+0

@Deeptechtons - я не думаю, что 'apply' или 'call' - любое использование этой проблемы, но, возможно, вы могли бы объяснить, что вы имели в виду в ответ? – nnnnnn

+0

@nnnnnn Вопрос определенно является кандидатом на вопрос «Как изменить контекст внутри функции». Что решается с помощью appy или вызова. Но для этого случая может быть излишним. – Deeptechtons

ответ

16

Магазин ссылка на this:

function a() { 
    var self = this; 
    self.b = 1; 
    self.set = setInterval(function() {console.log(self.b);}, 200); 
} 

Анонимная функция, которую вы передаете setInterval имеет доступ к любым переменным в содержащем его объем, то есть, любые локальные переменные function a(). Магия закрытий JS сохраняет эти переменные живыми даже после того, как a() завершил, и каждый вызов a() получает свое закрытие.

+0

Да, я видел такие примеры, но это именно то, что меня смущает. Предположим, что «а» заканчивается до того, как событие в 200 мс запускается, переменная «я» кажется, что она должна быть уничтожена в это время. Если нет, то когда оно будет уничтожено? после того, как интервал будет очищен? – NSF

+0

Как я уже упоминал в своем ответе, внутренняя функция имеет доступ к переменным в объеме своей содержащейся функции _ даже после завершения функции сохранения. В этом случае 'setInterval' продолжает удерживать ссылку на внутреннюю функцию, поэтому он может продолжать вызывать ее даже после завершения' a() '; пока интервал не будет очищен, эта ссылка останется в живых, а переменные останутся в живых. Обратите внимание, что 'a()' будет _definitely_ заканчиваться до того, как интервал будет запущен (независимо от того, как короткий интервал), потому что JS работает на одном потоке. Google «Закрытие JavaScript» для получения дополнительной информации. – nnnnnn

+0

иметь смысл. Благодарю. – NSF

2

Просто сохраните ссылку this в какой-либо другой переменной, которая не переопределяется window -коллами позже. Позже вы можете использовать эту переменную для ссылки на объект, с которым вы начали.

function a() { 
    this.b = 1; 
    var that = this; 
    this.set = setInterval(function() {console.log(that.b);}, 200); 
} 
0

В вашем случае, вы можете просто:

function a() { 
    var _this = this; 
    this.b = 1; 
    this.set = setInterval(function() { 
     console.log(_this.b); 
    }, 200); 
} 

Как правило, мы можем также вспомогательный метод Function.prototype.bind для затруднительногоthis ссылки.

4

Это будет чистым решением, так как большую часть времени вы на самом деле хотите, чтобы переключить этот контекст для последовательного вызова методов:

// store scope reference for our delegating method 
    var that = this; 
    setInterval(function() { 
     // this would be changed here because of method scope, 
     // but we still have a reference to that 
     OURMETHODNAME.call(that); 
    }, 200); 
3

Поскольку мы ES6 сейчас, я думаю, что нам нужен еще один ответ здесь :

Используйте функцию стрелки:

function a() { 
    this.b = 1; 
    this.set = setInterval(() => {console.log(this.b);}, 200); 
} 

функцию стрелки, напротив нормальные функции, не имеет this контекста на их своя. Это означает, что у вас есть доступ к внешнему this.

+1

ES6 сократил мой синтаксис почти до нуля, еще раз! Благодаря! – HoldOffHunger

Смежные вопросы