Подтвердить что ты не робот

Каков этот стиль asm "x | 0", который используют некоторые javascript-программисты?

Я видел некоторый критический код javascript с высокой критичностью, например, один из этот проект, который широко использует побитовые операции OR с 0. Пример:

GameBoyAdvanceCPU.prototype.write8 = function (address, data) {
address = address | 0;
data = data | 0;
this.memory.memoryWrite8(address | 0, data | 0);

Я знаю пример использования номеров напольных покрытий с "| 0", но здесь это не так, поскольку они всегда являются int. Это немного похоже на asm.js, так это сказать движку js, что мы работаем с целыми числами, что позволяет некоторые оптимизации? Если да, то какие браузеры сделают эти оптимизации?

Любые указатели на то, как это будет работать, будут рассмотрены.

4b9b3361

Ответ 1

Согласно Производительность JavaScript для Madmen

Арифметические выражения для целых чисел в ( ) | 0 позволяют времени выполнения убедиться, что вы выполняете целочисленную арифметику вместо арифметики с плавающей запятой. Это позволяет избегать проверки переполнения и более быстрого кода во многих случаях.

и в соответствии со страницей, это верно для "большинства" Javascript runtimes, но не говорит, что.

В качестве второго источника Написание быстрого JavaScript для игр и интерактивных приложений говорится

Чтобы сказать JavaScript-движок, мы хотим хранить целочисленные значения [...], мы могли бы использовать побитовое или операторное:

и третий источник из Написание эффективной страницы JavaScript в Microsoft:

[...] явно указывать время выполнения JavaScript для использования целочисленной арифметики [...] использовать побитовый или оператор

Кроме того, в комментариях ни одна из вышеперечисленных страниц не упоминает asm.js, поэтому я подозреваю, что такие оптимизации применяются в коде, явно не помеченном как asm/в браузерах, которые явно не распознают его.

Ответ 2

Ссылка спецификация Ecmascript 5: 11.10 двоичные побитовые операторы, а именно

Производство A : A @ B, где @ является одним из побитовых операторов в производные выше (&; ^; |) оцениваются следующим образом:

Пусть lref - результат оценки A.
Пусть lval be GetValue(lref).
Пусть rref - результат оценки B.
Пусть rval be GetValue(rref).
Пусть lnum be ToInt32(lval).
Пусть rnum be ToInt32(rval).
Верните результат применения побитового оператора @в lnum и rnum. Результатом является подписанное 32-битное целое число.

И отмечая, что ToInt32() определяется как

Пусть number является результатом вызова ToNumber на входном аргументе.
Если число NaN, +0, −0, +∞ или −∞, верните +0.
Пусть posInt be sign(number) * floor(abs(number)).
Пусть int32bit be posInt по модулю 2^32; то есть конечное целочисленное значение k типа number с положительным знаком и меньше чем 2^32 по величине, так что математическая разность posInt и k математически является целым числом, кратным 2^32. < ш > Если int32bit больше или равно 2^31, верните int32bit − 2^32, в противном случае верните int32bit.

Затем это логически следует (что вы можете подтвердить в своей собственной консоли), например

((Math.pow(2, 32)) + 2) | 0 === 2
(Math.pow(2, 31)) | 0 === -2147483648 === -(Math.pow(2, 31))

И так далее.

Короче говоря, операция превращает число в 32-битное целое число (которое имеет свои навыки, см. второй пример выше и определение ToInt32() для объяснения), а затем делает логическое или с нулевым, что не измените вывод за пределы первого преобразования.

По сути, это очень рентабельный способ превратить число в 32-разрядное целое, потому что 1) он полагается на встроенный браузер ToInt32(); и 2) ToInt32(0) коротких замыканий на 0 (см. выше спецификацию) и, следовательно, практически не добавляет дополнительных накладных расходов.

Ответ 3

Что это на самом деле можно увидеть в этом fiddle

Он исследует переменную типа integer в этом случае и либо "настил", либо устанавливает значение 0, если не целое число.

Таким образом, существует огромное отличие от a = a || 0, которое оставило бы значение 3.2 нетронутым.

Ответ 4

| оператор побитовое ИЛИ. Он выполнял побитовое ИЛИ операцию на двух целых.

Использование здесь - это ярлык, очень похожий на оператор логический ИЛИ || для предоставления значения по умолчанию, за исключением того, что результат является только целым (в отличие от строки... и т.д.)

address = address | 0;

означает "если адрес - это номер, пусть он его использует, в противном случае установите его на 0".