Рубрики
Без рубрики

От 0 до 9: магия чисел в JavaScript

Иногда цифры используются в мощных формах колдовства, как в JavaScript. И так же, как долго вы используете их правильным образом, цифры могут быть источником большого количества веселья в изучении JS.

Автор оригинала: Johnny B. (Ionică Bizău).

Числа имеют скрытую мощность. Иногда они используются в мощных формах колдовства, как в JavaScript. И так же, как долго вы используете их правильным образом, цифры могут быть источником большого количества веселья в изучении JS.

🤓 Примечание: Я собираюсь использовать ES2015 в следующих примерах. Не все будет работать Везде повсюду (вам нужен поддерживаемый интерпретатор ES2015, но не волнуйтесь, вероятно, вам не нужно заботиться о том, вы, вероятно, у вас уже есть). Некоторые из примеров являются ES2015. В этом случае есть конкретная заметка.

Итак, начнем!

Обучение JavaScript по номерам – от 0 до 9

0. Нулевые вещи

Как и на других языках программирования, индексы массива основаны на нулевой основе. Вы начинаете подсчитывать с нуля; Почему это так?

Первый : Упс, я попробую еще раз.

Ноль : Это о спасении пространства. Элементы из любого массива хранятся где-то в памяти.

Представьте себе, что память выглядит так:

Memory: _  _  _  _  _  _  _  _  _  _  _  _  _  
Data:                       [A, B, C]
                             ^ First index

Теперь, давайте предположим, что массив находится в памяти в Местоположение Х Отказ В нулевой индексации, чтобы получить доступ к элементу при индексе Я (Используя Array [I] ), компьютер должен: Получите мне контент в разделе «Расположение Х + я (например, для I , Массив [x + 0] будет первый элемент).

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

Memory: _  _  _  _  _  _  _  _  _  _  _  _  _  
Data:                       [   A, B, C]
                             ^ First index
                             ^ Unused memory gap

Так что местоположение Х сейчас не используется вообще, в то время как следующие используются. Если вы хотите использовать его, то вам нужно сделать вычитание ( Получить мне контент на x + I - 1 ), который объясняется в следующей точке.

Первый : Это о оптимизации вещей. Начало подсчета с нуля более эффективно. Давайте возьмем пример:

let fruits = ["Apples", "Pears", "Oranges"];
// Indexes:  0               1             2

Длина массива 3 (Есть три элемента). Можно сказать, что любой номер индекса соответствует следующему выражению математики:

0 ≤ index < 3

0 ≤ 0 < 3 → true
0 ≤ 1 < 3 → true
0 ≤ 2 < 3 → true

Теперь давайте посмотрим, что произойдет, если у нас есть одна индексация:

let fruits = ["Apples", "Pears", "Oranges"];
// Indexes:  1           2        3
let N = fruits.length;

1 ≤ index < N + 1

1 ≤ 1 < 4
1 ≤ 2 < 4
1 ≤ 3 < 4

Вы можете подумать: Ну, хорошо, в чем проблема здесь? Проблема в том, когда мы делаем N + 1 Отказ Это немного ненужной дополнительной работы для компьютера.

Второй : 1 Это наименьшее целое число, которое все еще является допустимым значением для непустой длины массива.

🤓 Примечание : Месяцы в датах JavaScript также являются нулевыми (0-11). Если вы хотите получить Первый из января 2016 года , ты хочешь сделать:

console.log(new Date(2016, 0, 1).toString())
→ Fri Jan 01 2016 00:00:00 GMT+0200 (EET)

Может ли это быть, потому что месяцы имеют этикетки, прикрепленные к индексам, так что быстрее доступа к ним внутренне (как я упоминал выше)? Может быть!

1. Представление номеров и работа с ними

Есть много способов представлять номера в JavaScript. Вот несколько из них. В некоторых случаях синтаксис выглядит странно, и даже если это действительный синтаксис, вы, вероятно, не будете использовать его. Но приятно знать, что такие случаи возможны.

Целые числа

> 42
42

// The dot is displayed only if there are non-zero digits after the dot
> 42.000
42

Плавающая запятая

> 3.14
3.14

Восьмерики (ака база 8)

Востанты используют ведущие 0 :

> 0123
83

Примечание. Приведенный выше формат запрещен в строгом режиме ES5. В ES6 мы можем использовать 0o ... :

> 0o123
83

Hex (AKA Base 16)

> 0xFF
255

> parseInt("0xFF", 16)
255

Экспонент

бывший Это аббревиатура для Умножьте на 10ˣ Отказ

> 7e3
7000

Объяснение:

7 * 10 * 10 * 10
    \__________/
7 *    (1)e3
7 *    1000
7000

💡 Совет : Это красиво работает с отрицательными показателями:

> 7e-2
0.07

Двоичный (добавлен в ES2015 +)

Начинается с 0b За ними последовал двоичный фрагмент ( 1 и 0 цифры).

> 0b1101
13

Играя с точкой:

> 42.
42

Для значений ниже 0, вы можете начать напрямую с точкой:

> .42
0.42

💡 Совет : Это работает в CSS:

div.myElement {
   opacity: .5;
}

2. Игра с номером конструктора

Все цифры выше имеют Номер конструктор:

> a = 42
42
> a.constructor
[Function: Number]
> typeof a
"number"

Итак, очевидно, они являются Числа Отказ Но одна вещь, которую мы должны помнить, это то, что в JavaScript все это объект. Итак, номера объектов в JavaScript? Конечно!

Простое доказательство – добавление нового метода для Номер опытный образец:

Number.prototype.me = function () {
    return this;
};

// Let's create a variable
let foo = 42;

// Obviously, it's a number
typeof foo;
// → "number"

// But let's use the `me` method which we added
// (it returns the Number instance)
typeof foo.me();
// → "object"

// And of course it can be used in operations
foo.me() + 1;
// → 43

Мы можем создать такие номера, используя Новый номер (...) Отказ

let a = new Number(42);
typeof a;
// → "object"

a + 1;
// → 43

// Note, by outputting this, we get an object:
console.log(a);
// → [Number: 42]

// Calling the valueOf will return the real number
console.log(a.valueOf());
// → 42

Это на самом деле полезно для чего-либо? Ну да!

Номер Конструктор можно использовать без Новый также. Он преобразует вещи в цифры (узнайте больше об этом здесь ):

let str = "\n\n42\t\n";
let foo = Number(str);
console.log(foo);
// → 42

Смесив эти две вещи вместе, мы можем создать наш собственный объект и вернуть настроить пользовательское преобразование, когда мы используем его в количестве операций:

let magicObject = {
    foo: 42
  , hello: "world"
    // This will return the numeric value 
  , valueOf () {
       return this.foo;
    }
};


// Let's convert it into a number
console.log(+magicObject);
// → 43

console.log(-magicObject);
// → -43

// Add 1 to the sum
console.log(magicObject + 1);
// → 43

// Additionally, you can set a custom stringify function:
magicObject.toString = function () { return this.hello; };

console.log(`Hello ${magicObject}!`);
// → "Hello world!"

3. Призывающие методы на цифровых литералах

Следующий синтаксис странный, но все же действует:

> .42.toString()
"0.42"

> 0.42.toString()
"0.42"

💡 Совет: Это хорошая практика, чтобы использовать упаковочные скобки вокруг таких чисел, и вот почему:

> (0.42).toString()
"0.42"

> (.42).toString()
"0.42"

> .42.toString()
"0.42"

> 0.42.toString()
"0.42"

// Note this: we do call the toString() function,
// but get a number in the end
> -0.42.toString()
-0.42

// When adding the wrapping parentheses, it's working fine
> (-0.42).toString()
'-0.42'

// But if we take the operator outside of the parentheses,
// we do get a number
> -(0.42).toString()
-0.42

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

   -0.42.toString()
//  \_____________/
// -     '0.42'
// -0.42

Когда вы завершаете свои номера между скобками, вы просто преобразуете (отрицательный) номер в строку.

4. Строго использовать строгий равный! ===! == == (ака строгий равный)

Как упоминалось в этой статье, это определенно лучше использовать строгую равную.

Если вы знаете немного JavaScript, это один из Первые вещи вы изучаете. На самых популярных языках программирования, чтобы проверить, что что-то равно что-то еще, вам придется использовать == :

// Assign the value
let foo = 42;

// Check if `foo` is 42
foo === 42
// → true

В JavaScript это работает, но это делает что-то еще. Это Либеральная равная , если вам нравится называть это так:

"42" == 42
// → true

// Add some spaces, new lines and tabs in that string
"\n\t 42 \t\n\n" == 42
// → true

Использование === (строгий равный) определенно делает изменение:

"42" === 42
// → false

5. Специальные номера

Есть довольно много специальных чисел:

  • -0 -Номативный ноль (обычно мы используем положительное значение: +0 или просто 0 )
  • Нан (не число)
  • Бесконечность и -Бесконечность

В Номер Объект вы найдете довольно много других констант:

// The largest representable number
> Number.MAX_VALUE
1.7976931348623157e+308

// The smallest representable number
> Number.MIN_VALUE
5e-324

// Special "not a number" value
> Number.NaN
NaN

// Special negative infinite value; returned on overflow
> Number.NEGATIVE_INFINITY
-Infinity

// Special positive infinite value; returned on overflow
> Number.POSITIVE_INFINITY
Infinity

// Difference between one and the smallest value greater
// than one that can be represented as a Number.
> Number.EPSILON
2.220446049250313e-16

// Minimum safe integer in JavaScript.
> Number.MIN_SAFE_INTEGER
-9007199254740991

// Maximum safe integer in JavaScript.
> Number.MAX_SAFE_INTEGER
9007199254740991

Кроме того, есть несколько констант в Математика объект (например math.pi , math.e и т. Д.).

6. Ловля -0.

Обратите внимание, что -0 === +0 это правда Отказ Но все же они делают совершенно разные вещи:

> 42 / 0
Infinity
> 42 / -0
-Infinity

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

7. Странные результаты и выражения

Как уже упоминалось выше, мы получаем (отрицательно) Бесконечность значения при разделении большинства чисел (отрицательно) ноль.

Но все же, есть несколько других случаев, когда мы получаем интересные результаты:

// Dividing zero by zero
0 / 0
→ NaN

// Note there is no -NaN
0 / -0
→ NaN

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

Math.pow(0, 0)
→ 1

Math.pow(NaN, 0);
→ 1

Бесконечность плюс все еще бесконечности:

Infinity + 42
→ Infinity

Infinity + Infinity
→ Infinity

Хотя вы получаете Нан Если вы вычитаете Бесконечность От себя:

Infinity - Infinity
→ NaN

Вы можете удивить, что в JavaScript, 0,1 + 0.2.3 неверно:

0.1 + 0.2 === 0.3
// → false
Что тут происходит?!

Ну, это связано с ошибками в точке с плавающей точкой. Давайте посмотрим смотреть:

> 0.1 + 0.2
0.30000000000000004

> 0.1 * 0.2
0.020000000000000004

Но почему это происходит?! Это из-за того, как компьютеры представляют номера внутренне. Краткое объяснение было бы: когда вы разделяете 1/3, вы, наверное, окружаете его на 0,333 ... Отказ Но если вы собираетесь на сумму 0,333 ... Три раза, вы получите 0,999 ... вместо 1 (Примечание. Равный х + 1 в реальном мире).

Итак, это просто из-за точности. Вы найдете лучшее и более длинные объяснения здесь ; И как решить такие проблемы.

Нуль равен нулю?

Вы бы сказали нет : null → false , но давайте посмотрим на это:

> null < 0
false
> null <= 0
true
> null === 0
false
> null == 0
false
> null >= 0
true
> null > 0
false

Итак, Что происходит здесь , очередной раз?! Ну, это JavaScript.

Как первый подсказка, мы можем проверить, как есть null преобразуется в номер: + Нуль0 Отказ С null преобразован в номер 0 Выражения сверхумеются смысл – кроме строгих равных. Объяснение легко: все остальные называют Отправляющий Операция с Номер как предпочтительный тип.

8. Нан (не число) вещь

Нан Очевидно, значит не число Отказ По иронии судьбы, Нан это Число (ну, у него есть номер тип):

typeof NaN // "number"
NaN.constructor // Number

Есть несколько способов назначить Нан к переменной:

// Just by using the `NaN` value
let foo = NaN; // NaN

// By parsing a non-number as number
parseInt("foo") // NaN

// Or shorter:
+'foo' // NaN

Иногда х

Потому что IEEE 754 диктует, что Нан там мы:

NaN !== NaN
→ true

Вот почему вы должны никогда не Проверьте, если Foo это не число Проверяя, если Foo Но, проверяя, если Foo или Isnan (foo) Отказ

Вы хотите создать еще одну подобную стоимость, делая то же самое?

Ну, мы можем попробовать что-то, что почти одинаково. Давай сделаем это:

// Let's define a property having a getter which returns a random number always
Object.defineProperty(this, "foo", {
   get () { return Math.random(); }
});

foo
→ 0.5300470317035524

foo
→ 0.4810690031991778

...

// Now, of course that:
foo !== foo
→ true

Однако, если вы создаете переменную и назначьте Foo Значение к нему, то он больше не будет работать (но он работает с Nan ):

> a = foo
0.2264466197115489
> a === a
true
> a = NaN
NaN
> a === a
false

9. Сила битовой операторы

Есть довольно много удивительных вещей, которые вы можете сделать с операторами низкого уровня, которые изменяют биты чисел.

Быстрое умножение/подразделения

Вы хотите умножить/разделить номер с мощностями 2 (2, 4, 8, 16 и т. Д.)? Вы хотите сделать это чрезвычайно быстрым? Затем ответ должен использовать << Оператор:

// Same with 3 * 2, but faster
> 3 << 1
6

// Same with 3 * 4
> 3 << 2
12

// Same with 3 * 8
> 3 << 3
24

// Divide by two
> 16 >> 1
8

Что происходит, в том, что << Перемещает все биты на левую позицию. Поскольку цифры представлены в двоичном двоике, добавляет новый 0 на правой стороне:

// 5 in base 2:
101

101 << 1
→ 1010 (which is 10 in base 2)

Подобные вещи случаются при использовании >> оператор.

Из моего тестирования, используя это << о 1.04 раз быстрее, чем использование * оператор. Может быть, имеет смысл, когда вы действительно заботитесь о производительности (например, оказание каких-то сложных 3D анимаций).

📝 Примечание : Это не работает для неигольников.

Проверка, если элемент включен в массив

Используя ~ (побитому не) побитовой оператор, чтобы найти, если элемент включен в массив:

let myArray = [1, 2, 42];
if (~myArray.indexOf(42)) {
   /* do something */
}

Что происходит, это то, что есть Индекс Это возвращает индекс элемента (в этом случае, 2 ), или -1 Если элемент не существует. -1 это единственное число, для которого ~ вернется 0 Отказ ~ повороты 0 в 1 и 1 в 0 на уровне битов.

~-1
→ 0

~0
→ 0

~42
→ -43

~-42
~41

Тогда, очевидно, 0 это ложное значение при преобразовании в логическое значение, а другие номера возвращаются ~ по-настоящему ценности. Итак, мы можем сделать что-то вроде этого:

let myArray = [4, 3, 42, 1];

// Get the index:
myArray.indexOf(42)
// → 2

// Let's check if it exists (convert to boolean)
!!~myArray.indexOf(42)
→ true

// ... and one which doesn't exist:
!!~myArray.indexOf(7)
→ false

Криптография веселья

Оператор XOR ( ^ ) действительно милый. Вы можете шифровать и расшифровать сообщения, используя его. Вот как это работает:

A   B   ^
=========
0   0   0
0   1   1
1   0   1
1   1   0

Это используется в криптографии. Простой пример будет ширина и расшифровывать номер:

// Alice and Bob know the same secret key:
let key = 42;

// Alice wants to send Bob a number
let msg = 7;

// But before sending it, Alice encrypts it:
msg = msg ^ key // or directly: msg ^= key
→ 45

// Bob receives 45, but knowing the key is 42 he knows to decrypt it:
45 ^ key
→ 7

// Now Bob can enjoy the message from Alice

Обертывание

Надеюсь, вам понравилось это прочитать, и вы что-то узнали! Веселитесь, используя цифры на благо этого мира. 🚀.