Где бы я использовал побитовый оператор в JavaScript?
Я прочитал этот (qaru.site/info/3175/...), поэтому я знаю , что побитовые операторы, но я все еще не понимаю, как их можно использовать... Может ли кто-нибудь предложить какие-либо реальные примеры того, где побито оператор будет полезен в JavaScript?
Спасибо.
Изменить:
Просто перейдя в источник jQuery. Я нашел пару мест, где используются побитовые операторы, например: (только оператор и оператор)
// Line 2756:
event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
// Line 2101
var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
Ответы
Ответ 1
Пример:
Вычисляет шестнадцатеричное значение для получения значений цвета RGB.
var hex = 'ffaadd';
var rgb = parseInt(hex, 16); // rgb is 16755421
var red = (rgb >> 16) & 0xFF; // returns 255
var green = (rgb >> 8) & 0xFF; // 170
var blue = rgb & 0xFF; // 221
Ответ 2
Я сильно использую побитовые операторы для числовых преобразований в производственных сценариях, потому что иногда они намного быстрее, чем их эквиваленты Math
или parseInt
.
Цена, которую я должен заплатить, - читаемость кода. Поэтому я обычно использую Math
в разработке и побитовом в производстве.
Вы можете найти некоторые трюки производительности на jsperf.com.
Как вы можете видеть, браузеры не оптимизируют Math.ceil
и parseInt
в течение многих лет, поэтому я прогнозирую, что побитовое будет быстрее и короче, чем делать в furure.
Дальнейшее чтение на SO...
Бонус: чит-лист для | 0
: простой и быстрый способ конвертировать что-либо в целое число:
( 3|0 ) === 3; // it does not change integers
( 3.3|0 ) === 3; // it casts off the fractional part in fractionalal numbers
( 3.8|0 ) === 3; // it does not round, but exactly casts off the fractional part
( -3.3|0 ) === -3; // including negative fractional numbers
( -3.8|0 ) === -3; // which have Math.floor(-3.3) == Math.floor(-3.8) == -4
( "3"|0 ) === 3; // strings with numbers are typecast to integers
( "3.8"|0 ) === 3; // during this the fractional part is cast off too
( "-3.8"|0 ) === -3; // including negative fractional numbers
( NaN|0 ) === 0; // NaN is typecast to 0
( Infinity|0 ) === 0; // the typecast to 0 occurs with the Infinity
( -Infinity|0 ) === 0; // and with -Infinity
( null|0 ) === 0; // and with null,
( (void 0)|0 ) === 0; // and with undefined
( []|0 ) === 0; // and with an empty array
( [3]|0 ) === 3; // but an array with one number is typecast to number
( [-3.8]|0 ) === -3; // including the cast off of the fractional part
( [" -3.8 "]|0 ) === -3; // including the typecast of strings to numbers
( [-3.8, 22]|0 ) === 0 // but an Array with several numbers is typecast to 0
( {}|0 ) === 0; // an empty object is typecast to 0
( {'2':'3'}|0 ) === 0; // or a not empty object
( (function(){})|0 ) === 0; // an empty function is typecast to 0 too
( (function(){ return 3;})|0 ) === 0;
и какая-то магия для меня:
3 | '0px' === 3;
Ответ 3
В JavaScript вы можете использовать двойное побитовое отрицание (~~n
) в качестве замены для Math.floor(n)
(если n
- положительное число) или parseInt(n, 10)
(даже если n
является отрицательным). n|n
и n&n
всегда дают те же результаты, что и ~~n
.
var n = Math.PI;
n; // 3.141592653589793
Math.floor(n); // 3
parseInt(n, 10); // 3
~~n; // 3
n|n; // 3
n&n; // 3
// ~~n works as a replacement for parseInt() with negative numbers…
~~(-n); // -3
(-n)|(-n); // -3
(-n)&(-n); // -3
parseInt(-n, 10); // -3
// …although it doesn’t replace Math.floor() for negative numbers
Math.floor(-n); // -4
Одно побитовое отрицание (~
) вычисляет -(parseInt(n, 10) + 1)
, поэтому два побитовых отрицания возвращают -(-(parseInt(n, 10) + 1) + 1)
.
Следует отметить, что из этих трех альтернатив n|n
представляется самым быстрым.
Обновление: Более точные этапы: http://jsperf.com/rounding-numbers-down
(как опубликовано на странной языковой функции)
Ответ 4
Пример реальной жизни?
^
(Побитовый XOR) в качестве I/O
toggler
Пример jsBin
Используется как value ^= 1
будет изменяться при каждом вызове value
на 0, 1, 0, 1 ...
Если мы передадим это value
в качестве Заявления в Условный оператор (?:)
, например,
statement ? (if true) : (if false)
и проверяя логическое представление 0=false, 1=true
, мы можем переключать текст, классы, стили.... все, что необходимо, например i.e: текст кнопки:
value ? "Close dropdown" : "Open dropdown";
Для одиночного элемента функция Toggle может выглядеть так:
// USING GLOBAL VARIABLE
var tog = 0;
var btn = document.getElementById('myButton');
function toggler(){
tog ^= 1;
this.innerHTML = tog ? "hide" : "show";
}
btn.addEventListener('click', toggler, false);
Для нескольких элементов мы можем сохранить состояние переменной tog
непосредственно в this
- ElementHTML
Object, например:
// WITHOUT GLOBAL VARIABLE
var btns = document.getElementsByClassName('myButton');
function toggler(){
var tog = this.tog ^= 1; // get/set tog value out of this.tog object
this.innerHTML = tog ? "hide" : "show";
}
for(var i=0; i<btns .length; i++){
btns[i].addEventListener('click', toggler, false);
}
Или, если вам не нравится идея this
, выберите стандартное свойство атрибута dataset
;)
Ответ 5
Учитывая успехи, которые делает Javascript (особенно с nodejs, который позволяет программировать на стороне сервера с помощью js), в JS все более сложный код. Вот несколько примеров, где я использовал побитовые операторы:
-
Операции IP-адреса:
//computes the broadcast address based on the mask and a host address
broadcast = (ip & mask) | (mask ^ 0xFFFFFFFF)
//converts a number to an ip adress
sprintf(ip, "%i.%i.%i.%i", ((ip_int >> 24) & 0x000000FF),
((ip_int >> 16) & 0x000000FF),
((ip_int >> 8) & 0x000000FF),
( ip_int & 0x000000FF));
Примечание: это код C, но JS почти идентичен
- Алгоритмы CRC часто используют их
Просмотрите запись в википедии на этом
- Операции с разрешением экрана
Ответ 6
Чтобы указать, является ли число нечетным:
function isOdd(number) {
return !!(number & 1);
}
isOdd(1); // true, 1 is odd
isOdd(2); // false, 2 is not odd
isOdd(357); // true, 357 is odd
Быстрее, чем модуль - используйте, где производительность действительно считается!
Ответ 7
Немногие другие примеры использования побитового и двойного побитового не:
Работа с полом
~~2.5 // 2
~~2.1 // 2
~~(-2.5) // -2
Проверить, не возвращается ли indexOf -1 или нет
var foo = 'abc';
!~foo.indexOf('bar'); // true
Ответ 8
Вы можете использовать их для отображения логического значения:
var foo = 1;
var bar = 0;
alert(foo ^= 1);
alert(bar ^= 1);
Это немного глупо, хотя и по большей части побитовые операторы не имеют большого количества приложений в Javascript.
Ответ 9
Битмаски.
Используется широко, например, в событиях JS.
Ответ 10
var arr = ['abc', 'xyz']
Досадно писать
if (arr.indexOf('abc') > -1) {
// 'abc' is in arr
}
if (arr.indexOf('def') === -1) {
// 'def' is not in arr
}
проверить, что-то внутри массива?
Вы можете использовать побитовый оператор ~
следующим образом:
if (~arr.indexOf('abc')) {
// 'abc' is in arr
}
if (! ~arr.indexOf('def')) {
// 'def' is not in arr
}
Ответ 11
Я использовал его один раз для виджета разрешений. Разрешения файлов в unix - это битовая маска, поэтому для ее анализа вам нужно использовать битовые операции.
Ответ 12
Я использую их для сглаживания трех чисел в 1 как способ хранения многомерных массивов в Uint16Array. Вот фрагмент игры воксела, которую я разрабатываю:
function Chunk() {
this._blocks = new Uint16Array(32768);
this._networkUpdates = [];
}
Chunk.prototype.getBlock = function(x, y, z) {
return this._blocks[y + (x << 5) + (z << 10)];
};
Chunk.prototype.setBlock = function(x, y, z, value) {
this._blocks[y + (x << 5) + (z << 10)] = value;
this._networkUpdates.push(value + (y << 15) + (x << 20) + (z << 25));
};
Chunk.prototype.getUpdates = function() {
return this._networkUpdates;
};
Chunk.prototype.processUpdate = function(update) {
// this._blocks[Math.floor(update / 65536)] = update % 65536;
this._blocks[update >> 16] = update & 65535;
};
var chunk = new Chunk();
chunk.setBlock(10, 5, 4);
alert(chunk.getBlock(10, 5, 4));
alert(chunk.getUpdates()[0]);
Ответ 13
Они кажутся очень полезными, когда вы работаете с шестнадцатеричными значениями и битами. Поскольку 4 бита могут представлять от 0 до F.
1111 = F
1111 1111 = FF.
Ответ 14
Пример использования Node.js
Предполагая, что у вас есть файл (называемый multiply.js) с этим содержимым, вы можете запустить
`node multiply <number> <number>`
и получить вывод, согласующийся с использованием оператора умножения на тех же двух числах. Переключение бит в функции Mulitply
является примером того, как взять битовую маску, представляющую один номер, и использовать ее для переворота бит в другом числе для быстрых операций.
var a, b, input = process.argv.slice(2);
var printUsage = function() {
console.log('USAGE:');
console.log(' node multiply <number> <number>');
}
if(input[0] === '--help') {+
printUsage();
process.exit(0);
}
if(input.length !== 2) {
printUsage();
process.exit(9);
}
if(isNaN(+input[0]) || isNaN(+input[1])) {
printUsage();
process.exit(9);
}
// Okay, safe to proceed
a = parseInt(input[0]),
b = parseInt(input[1]);
var Multiply = function(a,b) {
var x = a, y = b, z = 0;
while( x > 0 ) {
if(x % 2 === 1) {
z = z + y;
}
y = y << 1;
x = x >> 1;
}
return z;
}
var result = Multiply(a,b);
console.log(result);
Ответ 15
Я просто нашел этот вопрос, пытаясь подтвердить, был ли побитовый оператор AND
также &
в Javascript.
Поскольку вы попросили пример:
if ($('input[id="user[privileges]"]').length > 0) {
$('#privileges button').each(function () {
if (parseInt($('input[id="user[privileges]"]').val()) & parseInt($(this).attr('value'))) {
$(this).button('toggle');
}
});
}
Он заполняет состояние кнопок с помощью jQuery, учитывая значение битовой маски скрытого поля:
-
none
= 0
-
user
= 1
-
administrator
= 2
-
user
+ administrator
= 3