Я просматривал код из Mozilla, который добавляет метод фильтра в Array, и в нем была строка кода, которая смутила меня.

var len = this.length >>> 0;

Я никогда не видел & Gt ; & Gt ; & Gt ;, используемых в JavaScript ранее.
Что это такое и что оно делает?

Он не просто конвертирует не-числа в число, он конвертирует их в числа, которые могут быть выражены как 32-разрядные целые числа без знака.

Спасибо за решение Бена Келера. { *} и поле ввода получит фиксированный идентификатор <<, >>, &, | и ~) определены в терминах операций над 32-разрядными целыми числами. Выполнение побитовой операции преобразует число в 32-разрядное целое число со знаком, теряя все дроби и старшие разряды, чем 32, перед выполнением вычисления и последующим преобразованием обратно в число.

Таким образом, выполнение побитовой операции без реального эффекта, например, сдвиг вправо на 0 битов >>0, — это быстрый способ округлить число и убедиться, что оно находится в 32-битном диапазоне int. Кроме того, тройка >>>, выполнив свою операцию без знака, преобразует результаты своего вычисления в число как целое число без знака, а не целое число со знаком, как это делают другие, поэтому его можно использовать для преобразования отрицательных значений в 32-разрядную-двойную версию с дополнением как большое число. Использование >>>0 гарантирует, что у вас есть целое число от 0 до 0xFFFFFFFF.

В этом случае это полезно, потому что ECMAScript определяет индексы массива в терминах 32-битных беззнаковых целых. Поэтому, если вы пытаетесь реализовать array.filter таким образом, который точно повторяет то, что говорит стандарт ECMAScript Fifth Edition, вы должны преобразовать число в 32-битное целое число без знака, как это.

(На самом деле в этом нет особой практической необходимости, поскольку, надеюсь, люди не будут устанавливать array.length0.5, -1, 1e21 или 'LEMONS'. Но мы говорим об авторах JavaScript, так что вы никогда не узнаете …)

Резюме:

1>>>0            === 1
-1>>>0           === 0xFFFFFFFF          -1>>0    === -1
1.7>>>0          === 1
0x100000002>>>0  === 2
1e21>>>0         === 0xDEA00000          1e21>>0  === -0x21600000
Infinity>>>0     === 0
NaN>>>0          === 0
null>>>0         === 0
'1'>>>0          === 1
'x'>>>0          === 0
Object>>>0       === 0

(по крайней мере, в IE11):

Оператор смещения без знака без знака используется во всех реализациях метода IE войдет в бесконечный цикл загрузки страницы! метода Mozilla, чтобы гарантировать, что свойство length является беззнаковым 32-битным целочисленным Глядя на вывод

Переменная length свойством объектов массива: описан в спецификации как: Каждый объект Array имеет свойство длины, значение которого всегда является неотрицательным целым числом, меньшим 2

32 Этот оператор является кратчайшим путем для достижения этого, внутренними методами массива используйте операцию Глядя на вывод

, но этот метод недоступен и существует в спецификации для целей реализации. ToUint32 Дополнительные реализации

массива Mozilla стараются быть совместимыми с ECMAScript 5 , посмотрите описание метода (§ 15.4.4.14): Array.prototype.indexOf Как вы можете видите, они просто хотят воспроизвести поведение метода

1. Let O be the result of calling ToObject passing the this value 
   as the argument.
2. Let lenValue be the result of calling the [[Get]] internal method of O with 
   the argument "length".
3. Let len be ToUint32(lenValue).
....

в соответствии со спецификацией ES5 для реализации ES3, и, как я уже говорил, ToUint32 беззнаковый оператор смещения вправо является самым простым способом. Это оператор

беззнакового сдвига вправо . Разница между этим и оператором смещения правого бита в том, что оператор смещения правого бита (unsigned & Gt ; & Gt ; & gt ; ) заполняется нулями слева и & gt ; & gt ; ) заполняется знаковым битом, сохраняя при этом знак числового значения при сдвиге. Только хороший SEO для тех маршрутов, которые вы предоставляете специальную обработку & Gt ; & Gt ; & gt ; Дриис достаточно объяснил, что такое оператор и что он делает. Вот значение, стоящее за этим / почему оно использовалось:

Сдвиг любого направления на возвращает исходное число и приводит к приведению

. Кажется, что пример кода, который вы просматриваете, использует 0, чтобы гарантировать, что null0 является числовым, даже если this.length >>> 0 не определен.len является числовым, даже если this.length не определено.

Для многих людей побитовые операции неясны (и Дуглас Крокфорд / Jslint предлагает не использовать такие вещи). Это не означает, что это неправильно, но существуют более благоприятные и знакомые методы, которые делают код более читабельным. Более понятный способ убедиться, что len, 0 является одним из следующих двух методов.

// Cast this.length to a number
var len =  this.length;

или

// Cast this.length to a number, or use 0 if this.length is
// NaN/undefined (evaluates to false)
var len =  this.length || 0; 

>>> javascript — Как вернуть значение из асинхронной функции обратного вызова? — Переполнение стека unsigned оператор правого смещения (. ), в отличие от оператора правого смещения >>, Только хороший SEO для тех маршрутов, которые вы предоставляете специальную обработку .

>>> изменяет результаты сдвига отрицательных чисел, поскольку не сохраняет знаковый бит при сдвиге . Последствия этого можно понять на примере из интерпретатора:

$ 1 >> 0
1
$ 0 >> 0
0
$ -1 >> 0
-1
$ 1 >>> 0
1
$ 0 >>> 0
0
$ -1 >>> 0
4294967295
$(-1 >>> 0).toString(16)
"ffffffff"
$ "cabbage" >>> 0
0

Итак, что, вероятно, предполагается сделать здесь, это получить длину, или 0, если длина не определена или не является целым числом, согласно никогда не будет "cabbage" пример выше. Я думаю, что в этом случае можно с уверенностью предположить, что this.length. Тем не менее, я бы сказал, что < 0 этот пример — отвратительный взлом по двум причинам: Поведение

  1. при использовании отрицательных чисел, побочный эффект, вероятно, не предназначен (или может произойти) в приведенном выше примере. <<< Намерение кода не очевидно

  2. , поскольку существование этого вопроса подтверждает. Рекомендуется использовать что-то более читаемое, если производительность не является абсолютно критической:

Две причины:

isNaN(parseInt(foo)) ? 0 : parseInt(foo)

Результат & Gt ; & Gt ; & gt ; является «целым»

  1. undefined & gt ; & gt ; & gt ; 0 = 0 (поскольку JS попытается привести LFS к числовому контексту, это сработает для «foo» & Gt ; & Gt ; & Gt ; 0 и т. Д.)

  2. Помните, что числа в JS имеют внутреннее представление типа double. Это просто «быстрый» способ базового здравого смысла ввода для длины.

, -1 & Gt ; & Gt ; & Gt ; 0 (упс, скорее всего, длина не указана!)

Однако javascript — создание объекта с динамическими ключами — переполнение стека