Bit operations in Vue3

In the vue3 source code, there is a ShapeFlags implementation (element marking is normal element, function component, slot, keep alive component, etc.) which will not be expanded here.

export const enum ShapeFlags {
  ELEMENT = 1,
  FUNCTIONAL_COMPONENT = 1 << 1,
  STATEFUL_COMPONENT = 1 << 2,
  TEXT_CHILDREN = 1 << 3,
  ARRAY_CHILDREN = 1 << 4,
  SLOTS_CHILDREN = 1 << 5,
  TELEPORT = 1 << 6,
  SUSPENSE = 1 << 7,
  COMPONENT_SHOULD_KEEP_ALIVE = 1 << 8,
  COMPONENT_KEPT_ALIVE = 1 << 9,
  COMPONENT = ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT
}


 if (shapeFlag & ShapeFlags.ELEMENT || shapeFlag & ShapeFlags.TELEPORT) {
  ...
}


if (hasDynamicKeys) {
      patchFlag |= PatchFlags.FULL_PROPS
    } else {
    if (hasClassBinding) {
      patchFlag |= PatchFlags.CLASS
    }
    if (hasStyleBinding) {
      patchFlag |= PatchFlags.STYLE
    }
    if (dynamicPropNames.length) {
      patchFlag |= PatchFlags.PROPS
    }
    if (hasHydrationEventBinding) {
      patchFlag |= PatchFlags.HYDRATE_EVENTS
    }
}
Copy the code

Fragment of the code above is vue3 source code, including the < <, &, | = the several usual basically will not use operation method, this paper summarize the front need to master the operation.

Tips

In computers, when a number is stored, it is stored in the form of complement. And the complement of positive and negative numbers is represented differently. The complement of a positive number is equal to its original code, while the complement of a negative number is obtained by taking the original code except for the sign bits and then + 1.

Source code, inverse code, complement

  • Source code: The highest bit represents the sign bit, the positive number is 0, and the complex number is 1 (using the four-bits operation as an example).
10 = 01010 // source code -10 = 11010 // source codeCopy the code
  • “One’s complement” : complement from the original codeSign bit invariant, the positive number stays the same, and the negative number is the opposite, in order to solve+ 1- 1They don’t add up to0The problem of
10 + (-10) = 01010 + 10101 = 11111 = -0Copy the code
  • Complement: on the basis of the inverse code, the positive number is unchanged, and the negative number is added1(Two into one), solved+ 0and0The problem with two zeros.
-10 = 10110 // ComplementCopy the code

Hexadecimal conversion


/** * switch to other base *@param  {[type]} Num [number] *@param  {[type]} Radix [radix] *@return {[type]}       Return a radix radix number */
function convert(num,radix){
	return parseInt(num).toString(radix);
}
convert(123.2);

/** * Switch other bases to base 10 *@param  {[type]} Num [number] *@param  {[type]} Radix [radix] *@return {[type]}       Return a decimal number */
function convert10(num, radix){
	return parseInt(num, radix);
}
Copy the code

& (with), ~ (bitwise not), ^ (exclusive or) | (or)

&(bitwise and)

const a = 5; // 00101 const b = 3; // 00011 console.log(a & b); / / 00001 / / 1Copy the code

Truth table: (all values are 1, value is 1)

a b a AND b
0 0 0
0 1 0
1 0 0
1 1 1

Note: negative numbers take part in bitwise and operations as complement.

const a = 5;        / / 00101
const b = -3;        // 10011(original), 11100(negative), 11101(supplementary)

console.log(a & b); / / 00101
/ / 5
Copy the code

~ (bitwise non)

Invert each digit:

const a = 5;     / / 00101

console.log(~a); / / 11010. 6 = -
/ / - 6
Copy the code

Let’s take a look at the calculation steps of ~5:

  1. Convert 5 to binary =00000101
  2. Inverse = by bit11111010
  3. Finding that the sign bit (that is, the highest bit) is 1(representing a negative number), invert all other numbers except the sign bit =10000101
  4. Add 1 to the last digit to take its complement =10000110
  5. Convert back to decimal =- 6

Negative numbers, first find the complement, and then take the inverse.

Calculation steps of ~-5:

  1. So minus 5 to binary is equal to10000101
  2. The inverse of bits yields the inverse =11111010
  3. Add 1 to the last digit to take its complement =11111011
  4. Let’s take the inverse theta again00000100
  5. Convert back to decimal =4

In bitwise non-operation, the result of any number x is -(x + 1). For example, the result of ~ -5 is 4.

~ ~ and parseInt:

~ ~ 5.2 = - ((- (5 + 1)) + 1) - (- 6 + 1) = = = = = 5 parseInt (5.2)Copy the code

Bitwise operators are described in the ECMAScript® Language Specification as follows:

The production A : A @ B, where @ is one of the bitwise operators in the productions above, is evaluated as follows: 1. Let lref be the result of evaluating A. 2. Let lval be GetValue(lref). 3. Let rref be the result of evaluating B. 4. Let rval be GetValue(rref). 5. Let lnum be ToInt32(lval). 6. Let rnum be ToInt32(rval). 7. Return the result of applying  the bitwise operator @ to lnum and rnum. The result is a signed 32 bit integer.Copy the code

Note that in steps 5 and 6, the two values to be computed are first converted to signed 32-bit integers according to the ES standard. So integers larger than 32 bits are truncated, and decimals are discarded.

Bitwise elements discard decimal parts directly, so why not use bitwise operators in JavaScript?

^ (exclusive or)

If the same position is not equal, it is 1.

const a = 5;     / / 00101
const b = 3;     / / 00011

console.log(a ^ b); / / 00110
//  6
Copy the code

Truth table:

a b a XOR b
0 0 0
0 1 1
1 0 1
1 1 0

The xor operation of any number x with 0 results in x. Xor of any value x with -1 yields ~x.

Leetcode: a number that appears only once

Given an array of non-empty integers, each element appears twice except for one element. Find the element that appears only once. Note: Your algorithm should have linear time complexity. Can you do it without using extra space? Example 1: input: [2,2,1] output: 1Copy the code
var singleNumber = function(nums) {
    for(let i = 1; i<nums.length; i++) { nums[0] = nums[0] ^ nums[i]
    }
    return nums[0]};Copy the code

| (or)

A 1 in the same place is a 1.

const a = 5;     / / 00101
const b = 3;     / / 00011

console.log(a | b); / / 00111
//  7
Copy the code

5 | – 3 bitwise or negative:

  1. 5The original code =0000101
  2. - 3The original code =1000011, radix-minus-one complement =1111100, complement =1111101
  3. 5 | - 3 = 1111101
  4. Finding that the sign bit (that is, the highest bit) is 1(representing a negative number), invert all other numbers except the sign bit =1000010
  5. Add 1 to the last digit to take its complement =1000011
  6. Convert back to decimal =- 3

Truth table:

a b a OR b
0 0 0
0 1 1
1 0 1
1 1 1

<<(left move), >>(right move), >>>(unsigned right move),

< < (left)

The left-shift operator (<<) moves the first operand to the left by the specified number of digits. The excess left digit is cleared and the right digit is zeroed.

const a = 5; / / 00000101
a << 2 / / 00010100 = 20
Copy the code

a << 2 = a * 22 = a * 4 = 20;

a << 4 = a * 24 = a * 16 = 80;

> > (right)

This operator moves the first operand to the right by the specified number of digits. Bits moved to the right are discarded and the leftmost bits are copied to fill the left side. Since the new leftmost bit is always the same as before, the sign bit is not changed. That’s why it’s called “symbol propagation.”

const a = 5; / / 00000101
a >> 2 / / 00000001 = 1
Copy the code

>>>(unsigned right shift)

This operator moves the first operand to the right by the specified number of digits. Bits moved to the right are discarded and the left side is filled with zeros. Because the sign bit becomes zero, the result is always non-negative. (Even if you move 0 bits to the right, the result is non-negative.)

const a = -5; / / 100... Original 00101-11... The 111010-11... 111011 fill
a >>> 2 / / 0011... 1110 = 1073741822
Copy the code

There are 32 bits in total. I’ve left out the middle bits. Unsigned shifts are most likely to be used in real development with rounded x >>> 0.

The slice method in LoDash:

function slice(array, start, end) {... length = start > end ?0 : ((end - start) >>> 0)
  start >>>= 0. }export default slice
Copy the code