В моих объектах javascript я обнаружил, что пишу следующее:
this_object = this;
Кажется это единственный способ передать переменные-члены во внешние функции ...
google.maps.event.addListener(this.marker, 'click', function() {
this.info_window.setContent('Chicago marker');
this.info_window.open(this.map,this.marker);
});
Это не работает, мне нужно скопировать объект в переменную-член и передать новый объект (и заменить все this
на this_object
)
Это выглядит некрасиво. Есть ли способ «лучше» или «чище», или это мой единственный вариант?
Конечно, есть метод получше. Он включает в себя создание функции, контекст которой this
уже привязан к конкретному объекту.
Чтобы контекст this
ссылался на текущий объект, вызовите метод bind()
для функции и передайте требуемый контекст в качестве параметра.
google.maps.event.addListener(this.marker, 'click', function() {
this.info_window.setContent('Chicago marker');
this.info_window.open(this.map,this.marker);
}.bind(this)); // <-- notice we're calling bind() on the function itself
Теперь это часть стандарта ECMAScript, и если браузер не реализует его изначально, это легко сделать самостоятельно.
if (!Function.prototype.bind) {
Function.prototype.bind = function () {
var fn = this,
args = Array.prototype.slice.call(arguments),
object = args.shift();
return function () {
return fn.apply(
object, args.concat(Array.prototype.slice.call(arguments))
);
};
};
}
См. все вопросы и ответы по SO, связанные с этим.
Вы найдете эту часть код довольно часто встречается во многих библиотеках и проектах:
function someFunction() {
var that = this;
//....
}
Например, рассмотрим эту функцию:
function container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
return function () {
if (dec()) {
return that.member + " " + secret;
} else {
return null;
}
};
}
var c = container("foo");
alert( c() ); // "foo 2";
alert( c() ); // "foo 1";
alert( c() ); // "foo 0";
alert( c() ); // null;
Подробнее здесь.
Я видел шаблон раньше (с вызываемой переменной), поэтому я предполагаю, что это действительно распространенный шаблон javascript, который не просто имеет более чистое решение.
Я не уверен, что это поможет в любом сценарии, с которым вы имеете дело, но я обнаружил, что утилита пользовательских событий YUI хорошо работает с проблемами области видимости с помощью это и замыкания. Это модель, управляемая событиями, и немного другой способ мышления, но, по крайней мере, ее стоит изучить.
На самом деле при работе с JavaScript довольно распространена практика сохранения ссылки this
в локальной переменной, т. е. var myThing=this;
. Помните, что функции имеют доступ к локальным переменным, определенным в их области видимости. Доступны любые переменные, определенные в содержащих функциях.