#javascript #this #setinterval
#javascript #это #setinterval
Вопрос:
У меня есть метод, который представляет собой большой оператор setInterval, и ему нужен доступ к this объекту объекта, которому принадлежит метод, изнутри интервала. Я реализовал простое закрытие, но оно не кажется очень элегантным:
connect: function(to, rate, callback){
var cthis = this, //set cthis to this,
connectIntervalID = setInterval(function(){
if(cthis.attemptConnect(to)){ //reference it here,
clearInterval(connectIntervalID)
cthis.startListening(10) //here,
callback amp;amp; callback.apply(cthis, []) //and here
}
}, rate)
}
Вы также могли бы сделать это с помощью apply или call, если вы хотите использовать this вместо cthis
connect: function(to, rate, callback){
var cthis = this,
tempFunc = function(){
if(this.attemptConnect(to)){
clearInterval(connectIntervalID)
this.startListening(10)
callback amp;amp; callback.apply(this, [])
}
}�
connectIntervalID = setInterval(function(){tempFunc.apply(cthis, [])}, rate)
}
Однако это кажется еще хуже…
Комментарии:
1. Это JavaScript, к лучшему или к худшему.
Ответ №1:
Использование a .bind
делает это немного лучше (на мой взгляд, вы можете согласиться, а можете и не согласиться):
код поддержки:
function $A(args){
var out = [];
for(var i=0, l=args.length; i<l; i ){ out.push(args[i]); }
return out;
}
Function.prototype.bind = function() {
var __method = this, args = $A(arguments), object = args.shift();
return function() {
return __method.apply(object || this, args.concat( $A(arguments) ));
};
};
и ваш код становится:
connect: function(to, rate, callback){
connectIntervalID = setInterval((function(){
if(this.attemptConnect(to)){ //reference it here,
clearInterval(connectIntervalID)
this.startListening(10) //here,
callback amp;amp; callback.apply(this, []) //and here
}
}).bind(this), rate)
}
Но я боюсь, что у вас не получится намного лучше.
Комментарии:
1. MDC отмечает, что реальный метод привязки ES5 отличается по поведению — вы захотите протестировать как в ES5, так и в браузерах, отличных от ES5. developer.mozilla.org/en/JavaScript/Reference/Global_Objects /…
Ответ №2:
Ваш первый пример является более или менее стандартным способом сделать это. Моим единственным предложением было бы назвать вашу переменную как-то иначе, чем cthis; сделайте ее описательной для привязываемого объекта.
Javascript 1.8.5 добавляет Function.prototype.bind для решения этой проблемы другим способом, но это не является полезным решением для большинства людей.
Комментарии:
1. Почему
bind
это не полезное решение для большинства людей? Тривиально выполнить обнаружение функции и добавить ее, когда она не существует.2. @theazureshadow это полезно, но только если вам это нужно неоднократно. Для одноразового использования код обнаружения функций и поддержки того не стоит.
3. @Box9: Я понимаю, к чему вы клоните, но я думаю, что многие люди сочли бы выигрыш в удобочитаемости оправданным при обычном использовании (особенно если они используют его в нескольких проектах всякий раз, когда возникает необходимость). Это полезный инструмент в наборе инструментов, потому что он описывает закрытие, а не оставляет его неявным (не говоря уже о потенциально случайном).
4. это 1.8.5, только в новейших firefoxes, которые я разрабатываю в Chrome 12, у которого есть 1.6 или 1.7, но в противном случае это сработало бы
Ответ №3:
Я бы выделил setInterval
функцию в ее собственную функцию, прикрепленную к тому же объекту, что и connect
. Таким образом, будет ясно, что this
относится к одному и тому же объекту:
connect: function (to, rate, callback) {
var obj = this;
var intervalId = setInterval(function () {
obj.connectInterval(intervalId, callback);
}, rate);
},
connectInterval: function (intervalId, callback) {
if (this.attemptConnect(to)) {
clearInterval(intervalId);
this.startListening(10);
callback amp;amp; callback.apply(this, []);
}
}