Каков самый простой способ добавить флаг к числу в JavaScript без ущерба для его функциональности?

#javascript

#javascript

Вопрос:

Приведенный ниже код:

 var x = 600;
x.foo = true;
console.log("value: ",x);
console.log("foo: ",x.foo);
  

очевидно, что это не сработает, так как JS-числа распакованы. Очевидной альтернативой было бы вставить все ваши числа:

 var x = { value: 600, foo: true }
console.log("value: ",x.value);
console.log("foo: ",x.foo);
  

но предположим, что вы используете этот метод в дорогостоящем числовом приложении. Тогда вы получаете сильное замедление, так как теперь вы создаете объект в штучной упаковке для каждого отдельного числа в вашем алгоритме, что приведет к хаосу в управлении памятью среды выполнения. Однако, если все, что вам нужно, это флаг, более легким вариантом будет что-то вроде:

 var x = flag_as_foo(600);
console.log("value: ",extract_value(x));
console.log("foo: ",is_foo(x));
  

где flag_as_foo, flag_as_not_foo, is_foo and extract_value можно было бы работать, переворачивая биты числа или, возможно, используя какую-то умную арифметику. Мой вопрос в том, каков наилучший способ реализовать его в JavaScript? Это не очевидно, учитывая, что в JS нет целых чисел и необычный способ обработки чисел.

Пожалуйста, прочитайте вопрос. Я специально прошу побитовое или арифметическое решение для пометки числа.

Комментарии:

1. Я не понизил голос, но; может быть, вам следует привести несколько четких примеров того, чего вы не хотите. «… без использования массивов / объектов» в целом дисквалифицирует довольно фундаментальные функции языка. Любое решение, которое связывает два значения (число и флаг), будет иметь где-то какой-то объект. Использование new Number приемлемо или нет?

2. @fernozzle — Технически все в JavaScript является расширением Object , но в документации также говорится, что Number является одним из примитивных типов.

3. @fernozzle 2 отличается от new Number(2)

4. @Viclib Есть ли какая-нибудь функция на каком-нибудь языке, которая позволяет делать то, что вы хотите, без использования объекта (number), о котором я не знаю? Может быть, я упускаю что-то очевидное

5. @Ian Ну, сегодня я кое-что узнал. Но при каких обстоятельствах (2) действует иначе, чем Number(2) ?

Ответ №1:

На самом деле в JavaScript есть логические целые числа, которые используются при использовании определенных операций, таких как побитовые логические значения и сдвиги. Вот набор функций, которые соответствуют вашим критериям, предполагая, что вы работаете только с целочисленными значениями:

 function flag_as_foo(n) {
    n = n << 1;
    return n | 1;
}

function extract_value(n) {
    return n >> 1;
}

function is_foo(n) {
    return !!(n amp; 1);
}

var x = flag_as_foo(600);
console.log("value: ",extract_value(x));
console.log("foo: ",is_foo(x));
  

Это резервирует младший значащий бит в качестве флага. Число, конечно, не может использоваться как правильное значение без его прогона extract_value (как вы указали), поскольку x здесь используется не как целое число, а как строка битов (первые 31 из которых представляют число, а 32-й — флаг).

Обратите внимание, что максимальное количество используемых числовых битов здесь становится 31, что ограничено логическим оператором ECMAScript ToInt32 .

Комментарии:

1. Интересно, вы получили вопрос. Могу ли я по-прежнему использовать числа как числа с плавающей запятой?

Ответ №2:

Это самое близкое, что вы можете получить:

 var a = new Number(1), b = new Number(2);
a.isBlue = true;        //you can do this since a and b are now an Object

console.log(a b);       //3
console.log(a.isBlue);  //true
  

Одним из основных недостатков является то, что вам нужно приложить дополнительные усилия, чтобы проверить, совпадают ли два числа:

 a == b                  //false (assuming both have the same value)
  

Поскольку теперь они являются объектами, вам придется сделать это:

 a.valueOf() === b.valueOf() //true
  

Обновить:

Если вы используете побитовое или арифметическое решение для пометки числа, я бы использовал знак числа (при условии, что у вас есть только возможные числа.) В противном случае я не могу придумать ни одного простого решения.

Ответ №3:

учитывая, что в JS нет целых чисел

Для начала вы не можете хранить какой-либо флаг в int. Тем не менее, лучшим вариантом было бы использовать объектный литерал. Я понимаю, что вы указали в своем вопросе, что не хотели использовать объекты. Тем не менее, делая что-то вроде

 var a = {"number": "1337" , "color": "blue"}; 
alert(a.color);
  

кажется, это имеет наибольший смысл.

Комментарии:

1. Это невозможно, когда вы используете эти числа в дорогостоящем приложении. Т. Е. это невыносимо медленно.

2. Я понимаю. Теперь с вашим более подробным вопросом я понимаю. Спасибо