2013-12-05 2 views
3

Когда я запускаю эту строку кода:Array.push.call на окне/глобальных и числовых свойств

> var new_arr_length = Array.prototype.push.call(this, null); 

Я получаю очень странные результаты.

MDN documentation говорит, что push() должна возвращать длину массива, к которому толчок был применен к:

Returns

The new length property of the object upon which the method was called.

, но это то, что вы получите за:

> new_arr_length 
  • в Chrome вы получаете 17, потому что изначально свойства 0 - 15 ()) "DOMException".

  • в Node.js вы получаете 1. Здесь this будет объектом global.

  • в Safari вы получаете 3 потому что изначально, свойства 0 и 1 этого (window) равна Window

  • и в Firefox вы получите TypeError: setting a property that has only a getter ошибку

приводит меня спросить следующие вопросы:

  1. Почему Chrome "DOMException" s от this[0] до this[15]?

  2. Почему Safari Window для this[0] и this[1]?

  3. Почему Firefox единственный, кто бросает TypeError, и другие браузеры с радостью выполняют Array методов на Object?

Конечно, эта конкретная строка кода является уродливой и просто экспериментом, а не чем-то, что используется в живых проектах.

Спасибо заранее!

+4

Прежде всего вы должны знать, что для спецификации требуется, чтобы глобальный объект имел несколько свойств (http://es5.github.io/#x15.1), среда может добавлять любое количество дополнительных свойств , Кроме того, глобальный объект является объектом * хоста *, т. Е. Его поведение лишь частично продиктовано спецификацией. Все это означает, что вы должны ожидать, что глобальный объект имеет разные свойства в разных средах. –

+0

Да, я догадался, что это как-то связано со стандартами или в этом случае нестандартным поведением. Две вещи, которые казались странными, заключались в том, что «1) числовые свойства содержали ссылки на одно и то же в кажущихся случайными местами» и «2». Некоторые браузеры позволяют Window/Global вести себя как Array, а некоторые (например, Firefox). Кажется, это какая-то большая разница. –

+0

В последнем Chrome, Opera, IE11, прежде чем нажать, я получил результат длины 0 после 1. Как вы получили эти результаты? – Givi

ответ

1

Несколько вещей:

1) Обычно, window[n] для п целое число было бы Окно п-го подрамника на странице. Это то, что Гиви видит в комментариях на странице без фреймов: длина 0 и индексированные свойства и то, что вы видите в Safari.

2) На закладке «Новая вкладка» Chrome есть куча тегов. 17 из них, здесь. Быстро глядя на него, window[0] через window[16] - это фактически объект Window для этих подкадров на этой странице. Я понятия не имею, почему вы видите DOMException.

3) Методы массива, включая Array.prototype.push, являются в основном родовыми. То есть их определение таково, что они работают на любом объекте, а не только на массиве. Если вы посмотрите на spec на http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.push, вы увидите, что все push делает это .length, если этот объект, затем установите n на эту длину, затем для каждого из переданных аргументов установите thisObj[n] = argument (вид, см. Пункт 4 ниже) и приращение n на 1. И затем в самом конце установите this.length = n. Это все операции, которые обычно имеют смысл для любого объекта.

4) Если вы внимательно посмотрите на то, как push фактически определяется, что это на самом деле делает для того чтобы установить свойство n является Put(O, ToString(n), E, true). Если вы посмотрите на http://people.mozilla.org/~jorendorff/es6-draft.html#sec-put-o-p-v-throw, вы увидите, что последний аргумент заключается в том, следует ли генерировать исключение, если вызов [[Set]] терпит неудачу. Теперь, если вы действительно попытаетесь установить индексированные свойства в окне в Firefox, наборы фактически не работают. В строгом режиме вы получаете исключения; в нестрогом режиме наборы молчат без-ops. На самом деле это поведение, требуемое спецификацией WebIDL, в http://heycam.github.io/webidl/#defineownproperty (в частности, шаг 1 подэтап 4, если индекс не имеет дочернего окна на нем, а шаг 1 - подэтап 5, если индекс имеет дочернее окно на нем, поскольку в Окне нет ни одного индексированный установщик свойств и создатель индексированного свойства). Другие браузеры еще не реализовали эту часть спецификации, предположительно. Я должен отметить, что Firefox тоже не реализует его. В данном случае он использовал, как вы заметили, на Put(O, "length", n, true), но текущие ночные часы не потому, что length был закреплен как сменное свойство, поэтому его можно фактически установить. Но как только https://bugzilla.mozilla.org/show_bug.cgi?id=828137 будет установлен, он снова будет бросать.

+0

Эй, спасибо за очень необходимое дополнение деталей! –

+0

@m_vdbeek Добро пожаловать! –

Смежные вопросы