“This article has participated in the call for good writing activities, click to view: the back end, the big front end double track submission, 20,000 yuan prize pool waiting for you to challenge!”

preface

In this article you can learn about JS operators, some features, and some practical usage scenarios

Divided into primary > intermediate > Advanced

If you feel good or if you have anything to add, you can leave a comment

primary

Type conversion

String converts to nubmer

Number conversion some of you might write that

//before
const a = '123'

Number(a)	/ / 123
Copy the code

You can actually use either *1 or + to do implicit conversion

//after
const a = '123'

console.log(+a)    / / 123
console.log(a * 1)    / / 123
Copy the code

Additional examples of implicit conversions using +

'123'        / / 123
'ds'         // NaN
' '           / / 0
null         / / 0
undefined    // NaN
{ valueOf: () = >'3' }    / / 3
Copy the code

The number type is changed to string

//before
const a = 123
String(a)    / / '123'
Copy the code

You can use + ‘to do implicit conversion

//after
const a = 123
console.log(a + ' ')    / / '123'
Copy the code

Turns a Boolean type

Double!!!!! If cast directly to a Boolean, the true value will be converted to true and the false value will be converted to false

//before
Boolean(1)    //true

//after!!!!!123    //true
Copy the code

Use && to make logical decisions

In addition to making conditional judgment, because of its return value characteristics (if the first value is true, return the result of the next value, otherwise directly return the result of the previous value, the next value does not continue to evaluate), can also be used in logical judgment

// Conditional judgment
if(a === 1 && b ===2 ) {
    //todo
}
Copy the code

In fact, if can also be used to replace if when the logic inside is not complicated

const arr - [1.2.3]
const index = arr.indexOf(1)
//before
if(index === -1) {
    arr.splice(index, 1)}//after 
index === -1 && arr.splice(index, 1)
// This can also be simplified by using the bit operator '~', which can be seen further down.
Copy the code

If the value is one of two values, you can also use this shorthand (this is the ES2020 syntax, be compatible).

// return b if a is true, otherwise return A
a &&= b

/ / is equivalent to
a = a && b
Copy the code

Using the | | do variable assignment

| | except for condition judgment, because the return value characteristics (the first value is true, it returns the result of the first value, if the first is false values, continued to check the results back, until the return true, return true, if there is value, not evaluated), can also be used in variable assignment

// Conditional judgment
if(a === 1 || b === 2) { 
    //todo
}

// Variable assignment
const a = null || 1
console.log(a)  / / 1

Copy the code

This abbreviation can also be used when the value is used as the default value, but this is ES2020 writing, so be compatible

// If the box tag has a value, use this value. If it has no value, use the default value
document.getElementById('box').innerHTML ||= '
      
I'm the default text
'
/ / is equivalent to document.getElementById('box').innerHTML = document.getElementById('box').innerHTML || '
I'm the default text
'
Copy the code

Optional link operators (? .).

Optional link operators? In phase 4 of the ES2020 proposal, use Babel compatibility

When we use? If the value is false, execution is stopped and undefined is returned

Usually we develop if there is a field in the data at the back end is an array, we need to operate it, in case we will generally make array judgment, to prevent the subsequent execution from being affected because of errors

//before
const data = []

if(data && data.length) {
    //todo
}

//after
if(data? .length) {//todo
}
Copy the code

Or if the value of the object might be empty, so calling the method would report an error

constres = obj? .name()// This will not execute, and will not return error, just return undefined
Copy the code

Dynamic variable names and array values can also be followed

constres = datas? .data? .[arrName]? .0]
Copy the code

Null-value merge operator (??)

Null-value merge operator (??) Is a logical operator that returns the right-hand operand if the left-hand operand is null or undefined, otherwise returns the left-hand operand.

?? And | | is a bit like, but the | | is false value judgment,?????? Null and undefined

/ / true value
const a = 1 ?? 'Default value'
console.log(a)    / / 1

/ / false values
const a = ' ' ?? 'Default value'
console.log(a)    / /"

//null
const a = null ?? 'Default value'
console.log(a)    // 'default'

//undefined
const a = undefined ?? 'Default value'
console.log(a)    // 'default'
Copy the code

You can also abbreviate it

let a = 1a ?? ='Default value'

/ / is equivalent to
a = a ?? 'Default value'

console.log(a)    / / 1
Copy the code

The intermediate

Bitwise non-operator (~)

A brief description of the bitwise non-operator ~

The bitwise non-operator ~ is the binary inverse symbol, the binary inverse symbol, the param 0 is 1,1 is 0,

And there’s a rule that if it’s positive, it’s minus x plus 1.

The following is a 32-bit binary example

1 = 0000 0000 0000 0000 0000 0000 0000 0001

~1 = 1111 1111 1111 1111 1111 1111 1111 1110

Copy the code

Now let’s talk about the situation in which this symbol is used

integer

You can use the two-bit operator ~~ to replace math.floor () for positive numbers and math.ceil () for negative numbers.

When the value is positive

const num = 6.6

//before
Math.floor(num)  / / 6

//after 
~~num   / / 6
Copy the code

When the value is negative

const num = -6.6

//before 
Math.ceil(num)      / / - 6

//after 
~~num   / / - 6
Copy the code

Check whether it equals minus 1

The value 0 when ~-1 is used to determine the value of indexOf

const arr = [1.2.3.4.5]
const index = arr.indexOf(1)

// index is 0, ~index is -1, -1 is true
~index && arr.splice(index, 1)
console.log(arr);   / / [2, 3, 4, 5]

Copy the code

The bitwise or operator (|)

Simple instructions under the bitwise or operator |

It requires at least two operands to compare, and returns 1 if only one of the counterpoints is 1, or 0 otherwise

Let’s take 10 and 18

10 = 0000 0000 0000 0000 0000 0000 0000 1010
18 = 0000 0000 0000 0000 0000 0000 0001 0010

---------------------------------------------
10 | 18 = 0000 0000 0000 0000 0000 0000 0001 1010 = 26
Copy the code

Here are some scenarios where the bitwise xor operator ^ can be used

integer

Can use or operator | integer

6.66 | 0    / / 6

-6.66 | 0    / / - 6
Copy the code

Instead of Math. The round ()

/ / positive
const a1 = 1.4
const a2 = 1.6
a1 + 0.5 | 0   / / 1
a2 + 0.5 | 0   / / 2

/ / negative
const b1 = -1.4
const b2 = -1.6
b1 + 0.5 | 0   / / - 0
b2 + 0.5 | 0   // -1
Copy the code

Bitwise and operator (&)

Using the bitwise and operator & is actually the result of an alignment of operands.

Returns 0 if one of the counterpoints is 0, or 1 otherwise

10 = 0000 0000 0000 0000 0000 0000 0000 1010
1 =  0000 0000 0000 0000 0000 0000 0000 0001

---------------------------------------------
10 | 1 = 0000 0000 0000 0000 0000 0000 000 0000 = 0
Copy the code

Here are the scenarios in which the bitwise and operator & can be used

Judge odd and even

8 & 1    / / 0
7 & 1    / / 1

// 8 &1 is an odd number, and num &2 is an even number
if(8 & 1) {
    // If the logic is odd
}
Copy the code

Check if it is an integer power of 2

const a = 20;
const b = 32;

a & (a - 1) // 16 a is not an integer power of 2
b & (b - 1) // 0 b is an integer power of 2
Copy the code

Bitwise xOR operator (^)

Using the bitwise xor ^ is actually the result of an alignment of operands. Returns 1 if the alignment bits add up to 1, 0 otherwise

Take 32 bits as an example

10 = 0000 0000 0000 0000 0000 0000 0000 1010
18 = 0000 0000 0000 0000 0000 0000 0001 0010

--------------------------------------------
10 ^ 18 = 0000 0000 0000 0000 0000 0000 0001 1000 = 24
Copy the code

Here are the scenarios in which the lower xor operator ^ can be used

Toggle 0 and 1

When you switch on or off a class, you might use a variable to store 0 and 1, but you can toggle ^

//before
let toggle = 0

if(toggle) {
    toggle = 1
} else {
    toggle = 0
}

// Or use the ternary operator
toggle = toggle ? 0 : 1
Copy the code

It’s easier to do it the way you want to do it

let toggle = 0

toggle ^= 1  
console.log(toggle)    / / 1
Copy the code

Check whether two numbers have the same sign

const a = 1
const b = 2
const c = -1
const d = -2

(a ^ b) >= 0   // true
(a ^ c) >= 0   // false
(c ^ d) >= 0   // true
Copy the code

Determine whether the integer parts are equal

Because bitwise operators operate on positive numbers

// Both positive numbers
const a = 1
const b = 1

a ^ b    / / 0

/ / the decimal point
const a = 1.1
const b = 1.6

a ^ b    / / 0

Copy the code

Complete value exchange

We can also swap values of two variables using bitwise xor

let a = 1
let b = 2

a ^= b
b ^= a
a ^= b
console.log(a)   / / 2
console.log(b)   / / 1
Copy the code

However, this is actually a bit troublesome, in fact, using ES6 deconstruction is more convenient

let a = 1;
let b = 2;

[a, b] = [b, a]
console.log(a)   / / 2
console.log(b)   / / 1
Copy the code

The advanced

Shift left (<<)

The left shift is denoted by the symbol <<, which, as its name suggests, moves the binary of a numeric value to the left by the specified number of bits, then fills the space with 0, the sign bit unchanged (the highest bit is the sign bit)

2 = 0000 0000 0000 0000 0000 0000 0000 0010

// We move 2 to the left by 5
2 << 5 = 0000 0000 0000 0000 0000 0000 0100 0000 = 64
Copy the code

Left shift can also be used to round

1.66 << 0   / / 1
Copy the code

Move right (>>)

Represented by the symbol >>, the binary of a numeric value is moved to the right by the specified number of bits, with the signed bit unchanged and the empty space filled with 0, which is the opposite of the left shift

2 = 0000 0000 0000 0000 0000 0000 0000 0010

// We move 2 to the right by 2
2 >> 5 = 0000 0000 0000 0000 0000 0000 0000 0000 = 0


// For another example, we move 64 5 places to the right
64 = 0000 0000 0000 0000 0000 0000 0100 0000
64 >> 5 = 0000 0000 0000 0000 0000 0000 0000 0010 = 2
Copy the code

Unsigned right shift (>>>)

The >>> operator performs an unsigned right shift. It shifts all bits of an unsigned 32 – bit integer to the right. For an unsigned or positive right shift operation, the result of an unsigned right shift is the same as that of a signed right shift operation.

// Positive numbers are the same as >>
10 >> 2   / / 2
10 >>> 2   / / 2

// For negative numbers, the unsigned right shift will fill all Spaces with 0, and negative numbers will be treated as positive numbers, resulting in very large results so be careful when using the unsigned right shift operator to avoid accidental errors.
-1 >>> 0    / / 4294967295
Copy the code

Hexadecimal color values and RGB color values convert to each other

We mentioned left shift << and right shift >> earlier, now we show you how to use it

Hexadecimal color value to RGB:

function hexToRGB(hex){
    var hex = hex.replace("#"."0x"),
        r = hex >> 16,
        g = hex >> 8 & 0xff,
        b = hex & 0xff;
    return "rgb("+r+","+g+","+b+")";
}

hexToRGB("#ffffff")    / / RGB (255255255).
Copy the code

RGB to hexadecimal color value:

function RGBToHex(rgb){
    var rgbArr = rgb.split(/[^\d]+/),
        color = rgbArr[1] < <16 | rgbArr[2] < <8 | rgbArr[3];
    return "#"+color.toString(16);
}

RGBToHex("RGB (255255255)")    // #ffffff
Copy the code

Use bitwise operators for permission control

Assign permissions

Above we said that moving the binary code to the left << is to move the binary code to the corresponding digit

// The binary of 1 is 00000001

1 << 0  / / 00000001
1 << 1  / / 00000010
1 << 2  / / 00000100
1 << 3  / / 00001000
1 << 4  / / 00010000
1 << 5  / / 00100000.Copy the code

And you can see that there’s only one 1 in each of these numbers, and they’re all different, so if you combine them together, you’re actually going to be unique.

For example, in vuE-next’s PatchFlags. ts file, this section is the type mark of vNode in VisualDOM, which is used to update the DOM tree according to the different vNode type. Let’s look at the type definition

 * Patch flags can be combined using the | bitwise operator and can be checked
 * using the & operator, e.g.
 *
 * ` ``js * const flag = TEXT | CLASS * if (flag & TEXT) { ... } * `` `
 *
 * Check the `patchElement` function in'.. /.. /runtime-core/src/renderer.ts' to see how the
 * flags are handled during diff. * /export const enum PatchFlags {
  TEXT = 1./ / 1 < < 0
  CLASS = 1 << 1,
  STYLE = 1 << 2,
  PROPS = 1 << 3,
  FULL_PROPS = 1 << 4,
  HYDRATE_EVENTS = 1 << 5,
  STABLE_FRAGMENT = 1 << 6,
  KEYED_FRAGMENT = 1 << 7,
  UNKEYED_FRAGMENT = 1 << 8,
  NEED_PATCH = 1 << 9,
  DYNAMIC_SLOTS = 1 << 10.// SPECIAL FLAGS -------------------------------------------------------------

  // Special flags are negative integers. They are never matched against using
  // bitwise operators (bitwise matching should only happen in branches where
  // patchFlag > 0), and are mutually exclusive. When checking for a special
  // flag, simply check patchFlag === FLAG.
  HOISTED = -1,
  BAIL = -2
}

Copy the code

Here the author USES the < < is defined in addition to the type of features of 11 kinds of types, each of which is obtained by the left, the author comments on already gave tips, using | to permissions given, use & for permission to check

Permissions to

| we said above is for the operands are checked, contrapuntal digits only one is 1, it returns 1, otherwise it returns 0

Let’s create a permission and see

const permission = 0  // Initialize the role without permission
const permission1 = permission | TEXT | CLASS | PROPS

---------------------------------------------
 // As defined in the file above
  TEXT = 0000 0000 0000 0000 0000 0000 0000 0001
 CLASS = 0000 0000 0000 0000 0000 0000 0000 0010
 PROPS = 0000 0000 0000 0000 0000 0000 0000 1000

permission1 = permission | TEXT | CLASS | PROPS = 0000 0000 0000 0000 0000 0000 0000 1011 = 8
Copy the code

This grants a permission1 permission to manipulate TEXT, CLASS, and PROPS

Permission to check

We said that ampersand is used to compare the operands, and returns 0 if one of the counterpoints is 0, and 1 otherwise.

Now check permissions

// When permissions are granted
permission1 & TEXT

------------------------------------------------
permission1 = 0000 0000 0000 0000 0000 0000 0000 1011
       TEXT = 0000 0000 0000 0000 0000 0000 0000 0001

permission1 & TEXT = 0000 0000 0000 0000 0000 0000 0000 0001 = 1 = true


// When there is no permission
permission1 & STYLE

------------------------------------------------
permission1 = 0000 0000 0000 0000 0000 0000 0000 1011
      STYLE = 0000 0000 0000 0000 0000 0000 0000 0100

permission1 & STYLE = 0000 0000 0000 0000 0000 0000 0000 0000 = 0 = false

Copy the code

Remove permissions

The essence of a delete permission is to reset a 1 at a specified location to 0

We can use ^, ^ the rule is to return 1 if the alignment bits add up to 1, 0 otherwise

permission1 ^ TEXT

-------------------------------------------
permission1 = 0000 0000 0000 0000 0000 0000 0000 1011
       TEXT = 0000 0000 0000 0000 0000 0000 0000 0001

permission1 ^ TEXT = 0000 0000 0000 0000 0000 0000 0000 1010

Copy the code

If you do not have this permission, using ^ will increase the permission

Can be deleted before the judgment, or use &~ to delete

// If the delete permission exists
permission1 & (~TEXT)

-------------------------------------------
permission1 = 0000 0000 0000 0000 0000 0000 0000 1011
      ~TEXT = 1111 1111 1111 1111 1111 1111 1111 1110

permission1 & (~TEXT) =  0000 0000 0000 0000 0000 0000 0000 1010

// Delete permission does not exist
permission1 & (~STYLE)

--------------------------------------------
permission1 = 0000 0000 0000 0000 0000 0000 0000 1011
     ~STYLE = 1111 1111 1111 1111 1111 1111 1111 1011

permission1 & (~STYLE) = 0000 0000 0000 0000 0000 0000 0000 1011
Copy the code

reference

# “hardcore JS” will confuse you with bit arithmetic

# js bitwise operator and its clever use