Использование Function.prototype.apply для установки области обратного вызова javascript - PullRequest
9 голосов
/ 25 марта 2011

Огорчает необходимость вручную устанавливать область объекта каждый раз, когда я объявляю обратный вызов в JavaScript, но это факт жизни.Я подумал, смогу ли я сделать это, передав [mycallback] .apply в качестве обратного вызова, и объект области видимости в качестве аргумента, например так:

var f = function() { console.log(this.x); };
var o = {x: 3};
setTimeout(f.apply, 1000, o);

Насколько я могу судить, это должно вызвать f сo в качестве области действия, но вместо этого Chrome выдает «Uncaught TypeError: Function.prototype.apply был вызван для [объекта DOMWindow], который является объектом, а не функцией».Почему это не работает?

Ответы [ 3 ]

5 голосов
/ 25 марта 2011

По той же причине вам нужно «установить сферу» в первую очередь.На setTimeout отправляется только функция apply, связь с функцией f теряется.Таким образом, Javascript назначает глобальный объект window на this, как это было бы в любом другом случае.

Интересно отметить, что apply, будучи нативной функцией, не являетсяв некотором роде магический, и ведет себя в соответствии с пользовательскими функциями при установке переменной this.

4 голосов
/ 25 марта 2011

@ MooGoo ответ правильный, но, возможно, требуется более подробное объяснение.

Когда вы вызываете функцию apply на f следующим образом:

f.apply(ctx, args);

... затемвы выполняете apply в контексте f.

Но когда вы передаете ссылку на apply функции, например:

setTimeout(f.apply, 1000, o);

...это все, что вы делаете: передача ссылки на функцию f.apply.Это эквивалентно передаче Function.prototype.apply, потому что:

console.log(f.apply === Function.prototype.apply); // true

Любое соединение с f потеряно в window.setTimeout.Он получает ссылку на общую функцию apply из Function.prototype.Ничего более.Без контекста.

Следовательно, как и в любом другом случае, когда явный контекст не установлен, функция apply вызывается с window в качестве объекта контекста.

0 голосов
/ 25 марта 2011

Попробуйте это:

var f = function() { console.log(this.x); };
var o = {x: 3};
setTimeout(function(){f.apply(o)}, 1000);

У меня работает.

Заданное время ожидания ожидает функцию. Но поскольку apply - это встроенная функция, и вы не можете видеть нативный код за ней, она может не действовать как объект «function».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...