Первоисточник: http://twitter.com/tobeytailor/status/8998006366
(x=[].reverse)() === window // true
Я заметил, что это поведение влияет на все собственные типы. Что точно происходит здесь?
Это связано со странным способом эта
привязка работает в JavaScript.
[].reverse
- это метод reverse
для пустого списка. Если вы вызываете его через один из:
[].reverse();
[]['reverse']();
([].reverse)();
, тогда он выполняется с this
, привязанным к экземпляру списка []
. Но если вы его отсоединяете:
x= [].reverse;
x();
он выполняется без this
-binding, поэтому this
в функции указывает на глобальный объект ( window
), что является одной из худших и самых вводящих в заблуждение ошибок проектирования JavaScript.
(x=[].reverse)()
Также выполняет отсоединение. Оператор присваивания возвращает тот же функциональный объект, который был передан, поэтому похоже, что он ничего не делает, но имеет побочный эффект нарушения ограниченного особого случая, который заставляет JavaScript связывать this
.
Итак вы говорите:
Array.prototype.reverse.call(window)
обратный
, лайк Многие другие методы Array.prototype
определены ECMAScript для работы с любыми объектами, подобными нативным последовательностям. Он меняет местами элементы с ключами числовой строки (до object.length
) и возвращает объект. Таким образом, он вернет объект, который был передан для любого типа, имеющего свойство length
.
window
имеет свойство длины, которое соответствует window.frames.length
, поэтому вызов этого метода с this
, указывающий на window
, будет работать и верните окно
.Теоретически он все еще может не работать, потому что:
window
может быть «хост-объектом», а не «собственным объектом»; в этом случае не обязательно применяются гарантии того, что вы можете передать методам других прототипов; и Однако в текущих браузерах первый случай работает, а второй завершается неудачно без ошибок, поэтому вы по-прежнему получаете поведение === window
, а не исключение.