#javascript #object #methods #reference #eval
#javascript #объект #методы #ссылка #оценка
Вопрос:
Итак, у меня есть два объекта, a и b . Теперь я хочу передать один из методов b объекту a, который должен его сохранить. Давайте вызовем этот метод b.met:
b.met=function(){
alert(this.txt);
}
Теперь я хочу позвонить б.познакомился с а. Следующий код не работает, поскольку a.met является клоном b.met внутри области a:
a.met=b.met;
a.met(); //Executes in the 'a' scope!
Единственный способ, который я нашел на данный момент, — это сохранить имя метода в строке и использовать его в операторе eval:
a.toCall='b.met';
eval(a.toCall '();');
Поскольку все говорят, что вам следует избегать использования eval … какие еще есть возможности?
РЕДАКТИРОВАТЬ — смотрите в комментариях: Итак, я изменил свой код с:
a:{
processes:[],
spawnProcess:function(type,id,closeFn){
var closeFn=closeFn || 'function(){}';
this.processes.push({type:type,id:id,closeFn:closeFn});
}
Для:
a:{
processes:[],
spawnProcess:function(type,id,closeFn){
var closeFn=function(){closeFn()} || 'function(){}';
this.processes.push({type:type,id:id,closeFn:function(){closeFn()}});
}
При выполнении следующего кода я получаю ошибку слишком большой рекурсии:
a.spawnProcess('','',b.met);
a.processes[0].closeFn();
Комментарии:
Ответ №1:
Вы сохраняете ссылку на функцию. Функция — это просто функция. Это получает свое определение для this
на основе контекста вызова.
Итак, если вы сохраняете, a.met = b.met
а затем вызываете a.met()
внутри этой функции this === a
Прочитайте в JavaScript garden о this
Что вы хотите сделать, так это сохранить функцию и контекст для ее вызова.
Это может быть сделано либо как
a.met = function() {
b.met();
}
или
a.met = b.met.bind(b);
.bind
требуется ES5. Рекомендуемые кроссбраузерные альтернативы включают _.bind
и $.proxy
Редактировать
Вам нужно изменить
a.spawnProcess('','',b.met);
Для
a.spawnProcess('','', function() {
b.met();
});
Вы, вероятно, также хотите это вместо
a: {
processes: [],
spawnProcess: function(type, id, closeFn) {
this.processes.push({
type: type,
id: id,
closeFn: closeFn || function() {}
});
}
}
Комментарии:
1. Я еще не пробовал метод .bind, но я попробовал другое решение, которое вы мне дали, и оно не работает для того, что я пытаюсь сделать… Я поместил код в конец своего вопроса, может быть, вы могли бы взглянуть?
2. @Alex кстати, эмуляция процессов в javascript — плохая идея. Используйте web workers. (JavaScript является однопоточным)
Ответ №2:
Простейшее решение:
a.met = function() { b.met(); };
или используя .bind
(см. MDC) ту же семантическую:
a.met = b.met.bind(b);
Ответ №3:
Если ваших функций много и у них есть аргументы, вы также можете сделать это
function B() {
this.x = "I am b";
}
function A() {
this.x = "I am A";
}
B.prototype.met = function() {
alert(this.x);
}
A.prototype.met = B.prototype.met;
Вы можете обновить A.prototype с помощью функций, которые вам нужны из B.prototype.