Кто-то может объяснить этот метод JavaScript?

Первоисточник: http://twitter.com/tobeytailor/status/8998006366

(x=[].reverse)() === window // true

Я заметил, что это поведение влияет на все собственные типы. Что точно происходит здесь?

24
задан Esteban Küber 7 April 2010 в 21:06
поделиться

1 ответ

Это связано со странным способом эта привязка работает в 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 , будет работать и верните окно .Теоретически он все еще может не работать, потому что:

  1. window может быть «хост-объектом», а не «собственным объектом»; в этом случае не обязательно применяются гарантии того, что вы можете передать методам других прототипов; и
  2. если в окне действительно есть фреймы / фреймы, оно будет пытаться изменить их порядок, что не сработает, потому что коллекция фреймов доступна только для чтения.

Однако в текущих браузерах первый случай работает, а второй завершается неудачно без ошибок, поэтому вы по-прежнему получаете поведение === window , а не исключение.

40
ответ дан 28 November 2019 в 23:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: