The problem the forerunner

  • Let’s talk about HTML5dragAPI [HTML]
  • Implementation of two-column layout
  • Implementation of three-column layout
  • Common bitwise operators [JS basics]
  • Why is the implicit variable arguments in a function an array of classes instead of an array? 【 JS Basics 】
  • What’s the difference between BOM and DOM? 【 JS Basics 】
  • React and Vue 【Vue】
  • Advantages of Vue 【Vue】
  • What is the difference between assets and static directories? 【 Vue 】
  • Implement array de-duplication
  • Implement arrayflatMethod [Handwritten code]
  • Implement arraypushMethod [Handwritten code]
  • Code output results (Promise related)
  • Flipping binary tree
  • Sum of three numbers [algorithm]

Knowledge comb

Let’s talk about HTML5drag API

Drag events are drag events that are triggered when an element or text is pushed. Like mouse events, drag events have a more complete set of drag-and-drop events than mouse events. Drag events typically have two elements to listen for: the dragged element and the target element that receives the dragged element.

There are different ways to listen for events for two different elements:

  • Dragged element
    • dragstart: Triggered when the element is dragged
    • drag: Triggered when an element is dragged
    • dragend: Triggered when the drag ends
  • The target element
    • dragenter: triggered when an element is dragged into the target element.
    • dragover: Triggered when the dragged element moves within the target element
    • dragleave: Triggered when the dragged element leaves the target element
    • drop: Triggered when dragging ends within the target element

Note that if you want drop to fire, prevent dragover’s default event: event.preventDefault(); .

Reference:

  • drag – MDN

Implementation of a two-column layout

In a two-column layout, the left column has a fixed width and the right column has an adaptive width.

Assume the left width is fixed at 200px. The basic HTML structure is:

<div class="outer">
    <div class="left"></div>
    <div class="right"></div>
</div>
Copy the code

There are generally three schemes:

  1. Position using a float: float

    • Left floating positioning, set the width to a fixed width; Set margin-left to the left fixed width value, and set the width to auto to automatically fill the parent element.

      .outer {
          width: 500px;
          height: 500px;
          margin: 0px auto;
          border: 1px solid #ccc;
      }
      
      .left {
          float: left;
          
          width: 200px;
          height: 100px;
          background-color: #f59898;
      }
      
      .right {
          margin-left: 200px;
          
          width: auto;
          height: 300px;
          background-color: #9ed0c4;
      }
      Copy the code
    • Left floating positioning, and set a fixed width; Set over-flow: Hidden on the right so that Block Formatting Context (BFC) is triggered on the right. The BFC area does not overlap the floating elements.

      .right {
          over-flow: hidden;
          width: auto;
          
          height: 300px;
          background-color: #9ed0c4;
      }
      Copy the code
  2. Make use of absolute positioning

    • Set the parent element to relative positioning; The left element is set to absolute positioning and the width is set to a fixed width value. Set margin-left to a fixed width on the right and set the width to calc(100%-200px). Note that display needs to be replaced with an inline element such as display: inline-block.

      .outer {
          margin: 0px auto;
          width: 500px;
          height: 500px;
          border: 1px solid #ccc;
      }
      
      .left {
          position: absolute;
      
          width: 200px;
          height: 100px;
          background-color: #f59898;
      }
      
      .right {
          margin-left: 200px;
          
          height: 300px;
          background-color: #9ed0c4;
      }
      Copy the code
    • Set the parent element to relative orientation, the left element width to fixed width, the right element to absolute orientation, and the left element to a fixed width value.

      .outer {
          position: relative;
      
          margin: 0px auto;
          width: 500px;
          height: 500px;
          border: 1px solid #ccc;
      }
      
      .left {
          width: 200px;
          height: 100px;
          background-color: #f59898;
      }
      
      .right {
          position: absolute;
          width: calc(100% - 200px);
          top: 0px;
          left: 200px;
          height: 300px;
          background-color: #9ed0c4;
      }
      Copy the code
  3. Use the Flex layout: Set the left element width to a fixed value and the right flex to Auto or 1

    .outer {
        display: flex;
        width: 500px;
        height: 500px;
        margin: 0px auto;
        border: 1px solid #ccc;
    }
    
    .left {
        width: 200px;
        height: 100px;
        background-color: #f59898;
    }
    
    .right {
        flex: 1;
        height: 300px;
        background-color: #9ed0c4;
    }
    Copy the code

Implementation of three column layout

A three-column layout generally refers to a layout with three columns on the page, the left and right columns of fixed width, and an adaptive middle.

Similar to the two-column layout, the basic structure is:

<div class="outer">
    <div class="left"></div>
    <div class="right"></div>
    <div class="center"></div>
</div>
Copy the code
  1. Using floating

    Set the left and right elements to float left and right respectively, and the middle elements to margin-left and margin-right respectively.

    However, the div.center element must come after div.right, or the float will be wrapped.

    .outer {
        width: 500px;
        height: 500px;
        margin: 0px auto;
        border: 1px solid #ccc;
    }
    
    .left {
        float: left;
        width: 200px;
        height: 100px;
        background-color: #f59898;
    }
    
    .center {
        margin-left: 200px;
        margin-right: 100px;
        width: auto;
        height: 200px;
        background-color: #9ed0c4;
    }
    
    .right {
        float: right;
        width: 100px;
        height: 300px;
        background-color: #a99ed0;
    }
    Copy the code
  2. Make use of absolute positioning

    Set the parent element to relative positioning, the left and right sides to absolute positioning, and a margin in the middle. This is similar to the float positioning, but you don’t need to place div.center after div.right.

    .outer {
        position: relative;
        width: 500px;
        height: 500px;
        margin: 0px auto;
        border: 1px solid #ccc;
    }
    
    .left {
        position: absolute;
        left: 0px;
        top: 0px;
        width: 200px;
        height: 100px;
        background-color: #f59898;
    }
    
    .center {
        margin-left: 200px;
        margin-right: 100px;
        width: auto;
        height: 200px;
        background-color: #9ed0c4;
    }
    
    .right {
        position: absolute;
        right: 0px;
        top: 0px;
        width: 100px;
        height: 300px;
        background-color: #a99ed0;
    }
    Copy the code
  3. Positioning with Flex

    Set a fixed width on the left and right sides and flex:1 in the middle.

    .outer {
        display: flex;
        width: 500px;
        height: 500px;
        margin: 0px auto;
        border: 1px solid #ccc;
    }
    
    .left {
        width: 200px;
        height: 100px;
        background-color: #f59898;
    }
    
    .center {
        flex: 1;
        height: 200px;
        background-color: #9ed0c4;
    }
    
    .right {
        width: 100px;
        height: 300px;
        background-color: #a99ed0;
    }
    Copy the code
  4. The holy grail layout

    Use float and negative margin. Place the middle element first, then set the width to the width of the parent element, float all three columns to the left, so that the left and right elements are squeezed into the next row, and then move the two floating elements in the next row to the top row by setting the margin of the element to negative. Then use relative positioning to adjust the position of the left and right elements. Finally, set the padding of the parent element so that the left and right elements are within the padding.

    .outer {
        position: relative;
        margin: 0px auto;
        width: 500px;
        height: 500px;
        border: 1px solid #ccc;
        padding-left: 200px;
        padding-right: 100px;
    }
    
    .center {
        float: left;
        width: 100%;
        height: 400px;
        background-color: #9ed0c4;
    }
    
    .left {
        float: left;
        margin-left: -200px;
        position: relative;
        left: -100%;
        width: 200px;
        height: 100px;
        background-color: #f59898;
    }
    
    .right {
        float: left;
        margin-left: -100px;
        width: 100px;
        position: relative;
        left: 100px;
        height: 300px;
        background-color: #a99ed0;
    }
    Copy the code

    One problem with the Grail layout, however, is that when the main part of the panel is smaller than the width of the sub-panels on either side, the layout gets messed up. One problem with the Grail layout, however, is that when the main part of the panel is smaller than the width of the sub-panels on either side, the layout gets messed up. It was very difficult to achieve a more perfect layout, so the twin wing layout chose to add a TAB on the main panel.

  5. Twin wing layout

    In contrast to the Holy Grail layout, the left and right positions are reserved by the margin of the middle column, not by the padding of the parent element. Essentially, this is done by floating and margin negative values.

    <div class="outer">
        <div class="center-container">
            <div class="center"></div>
        </div>
        <div class="left"></div>
        <div class="right"></div>
    </div>
    Copy the code
    .outer {
        position: relative;
        margin: 0px auto;
        width: 500px;
        height: 500px;
        border: 1px solid #ccc;
    }
    
    .center-container {
        float: left;
        width: 100%;
    }
    
    .center {
        height: 400px;
        margin-left: 200px;
        margin-right: 100px;
        background-color: #9ed0c4;
    }
    
    .left {
        float: left;
        margin-left: -100%;
        width: 200px;
        height: 100px;
        background-color: #f59898;
    }
    
    .right {
        float: left;
        margin-left: -100px;
        width: 100px;
        height: 300px;
        background-color: #a99ed0;
    }
    Copy the code
    • The twin wing layout adds a parent TAB to the main panel to make room for the child panel through margin.
    • The Grail uses padding, while the wings use margin, which solves the problem of grail layout.
    • Dual wing layout does not set the relative layout, and the corresponding left and right values.

For more details: what is the Holy Grail layout and the Twin wing layout

If you are familiar with grid layouts, both two-column and three-column layouts can be implemented with grid layouts.

What are the common bitwise operators?

Operations between bits are called bitwise operations. Common bit operations are the following:

The operator describe algorithm
& with If both bits are 1, the result is 1
` or As long as one of them is 1, it’s going to be 1
^ Exclusive or The same bit is 0, and the different bit is 1
~ The not 0 becomes 1,1 becomes 0
<< Shift to the left All the binary bits move a number of bits left, high discard, low fill 0
>> Moves to the right All the binary bits move right several bits, positive left complement 0, negative left complement 1, the right discard

Bit operation because of the direct use of binary calculation, saving memory, so that the program calculation efficiency is higher, different bit operation has different purposes.

In JS, operations can be performed using the following operators:

Bitwise and (&)

If both are 1, the result is 1. For example, if 3&5 = 1, write binary as:

0000 0011 &
0000 0101 =
0000 0001
Copy the code

Use: judge numbers parity: n & 1 === 0 and n % 2 == 0 is the same.

Bitwise or (|)

As long as one of them is 1, it’s going to be 1. Such as 3 | 5 = 7:

0000 0011 |
0000 0101 =
0000 0111
Copy the code

Bitwise xor (^)

Identical is 0, dissimilar is 1. So 3 to the fifth is 6.

0000 0011 ^
0000 0101 = 
0000 0 110
Copy the code

A regular bit operation:

  • Reflexive:a ^ a = 0.a ^ 0 = a
  • Associative law:a ^ b ^ c = a ^ (b ^ c)
  • Commutative law:a ^ b = b ^ a(There’s nothing to say about this, and this is true of other bits.)

Chief among them is reflexivity, because commutative and associative operators generally have this property as well.

A ^ b ^ b = a ^ 0 = a. We can use this property to swap the values of a and B without using intermediate variables.

a = a ^ b
b = a ^ b
a = a ^ b
Copy the code

Take the inverse operator (~)

There’s nothing to say. Just swap zeros and ones.

Left shift operation (>>)

To move all bits of an operand to the left, discard the left bits and add zeros to the right.

Signed shift 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.”

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.)

Source, inverse, and complement

It is worth noting that binary is stored in the computer as a complement, the calculation of the same is the use of complement.

Numbers can be positive or negative, usually represented by the first bit, 0 for a positive number, 1 for a negative number, followed by the number of stored digits is the real value.

We find that binary doesn’t have subtraction, or it’s not easy to do subtraction, so what do we do with subtraction?

That’s an addition, like 1 minus 2 is the same thing as 1 plus minus 2. The concept of complement in encyclopedia introduces the concept of “modules”, such as a clock, which can represent only 0-11 hours of time, such a limited range of measurement system, called modules. The maximum measurement range of the measurement system is also called module, so the clock here can be regarded as a measurement system with module 12. In the clock system, if you want to adjust 8 hours to 6 hours, there are two methods: one is to dial back 2 hours, the other is to dial forward 10 hours, which is the difference between subtraction and addition: That is, 8-2 = 8 + 10. For 8 + 10, because it exceeds the measurement range of modules, only the remainder can be saved: 18-12 = 6. Therefore, the addition and subtraction here can be converted to each other, and this property is consistent with all modular measurement systems. For subtracting 8-2 to addition is 8 + (-2), we add the modulo to this negative number to get its “complement” 10, which is easy to add.

Computer measurement system is also a kind of mould, because the computer storage digits is limited, when over the limit, the number is lost, can only keep storage, such as a computer store digits only four, then the largest number is 1111, if you add up 1, becomes 10000, because of the limitation of mould can only save four, It goes back to 0000.

Due to binary subtraction operation is not convenient, we will be converted to add operation, in the mold system, subtraction turn addition is the complement and it can, for the convenience of calculation, is a complement of computer storage, to facilitate operations directly, as we know, complement + source = die, for the computer systems of binary, die is not fixed, But we found a way to calculate the negative complement: the complement = inverse + 1, which is to take the other bits except the sign bits. It is important to note that both complement and inverse are for negative numbers because positive numbers do not require subtraction-to-addition conversions.

The calculation principle of complement is very simple: source code + inverse code = 11111… , that is, all 1s, plus 1, get modulus, so the original code + inverse code + 1 = modulus, so the complement = inverse code + 1.

Why is the implicit variable arguments in a function an array of classes instead of an array?

  • Bitwise operators

Why are functions implicit variablesargumentsClass array instead of array?

Arguments [n] (n ∈ [0, arguments.length – 1)); arguments[n] (n ∈ [0, arguments.length – 1); arguments[n] (n ∈ [0, arguments.length – 1)); arguments[n] (n ∈ [0, arguments.length – 1)); And these subscripts are iterable. Arguments access elements just like an array, but arguments doesn’t have any of the other properties and methods of an array, and has its own properties like Callee. Therefore, arguments is just an array of classes and not a real array. Just use array.from (arguments).

What’s the difference between BOM and DOM?

BOM is the Browser Object Mode, or Browser Object model. To facilitate interaction with JavaScript, the Browser is abstracted into a JavaScript Object. This is BOM, which can be understood as the abstraction of the Browser, also known as the Window Object.

And DOM full name Document Object Mode, namely Document model Object, the Document here, is HTML Document, also in order to facilitate interaction with JS, is abstracted into a Document Object, is also a JS Object.

The DOM object is contained within the BOM object.

React and Vue, similarities and differences

The official notes themselves: contrast with other frameworks.

Similarities:

  • Both keep their focus on the core library, leaving other functions such as routing and global state management to related libraries;
  • Each has its own build tool that lets you get a project template set according to best practices;
  • Both use the Virtual DOM to improve redraw performance;
  • Both have the concept of props to allow data transfer between components;
  • Both encourage componentized applications, which are broken down into functional modules to improve reusability.

Differences:

1) Data flow

Vue supports bidirectional data binding by default, while React has always advocated one-way data flow

2) Virtual DOM

The introduction of the “Virtual DOM” eliminates the difference between React and Vue2. X, however, still has its own features in specific details.

  • Vue claims to be able to calculate Virtual DOM differences faster because it tracks the dependencies of each component during rendering, without having to re-render the entire component tree.
  • With React, all child components are rerendered whenever the state of the application is changed. Of course, this can be achieved by PureComponent/shouldComponentUpdate the lifecycle methods to control, but the Vue see this as the default optimization.

3) Componentization

The biggest difference between React and Vue is the writing of templates.

  • Vue encourages writing templates that are similar to regular HTML. It’s written pretty much like a standard HTML element, with a few more attributes.
  • React recommends that all of your templates use JavaScript syntax extensions called JSX writing.

React’s Render function supports closures, so import components can be called directly in Render. In Vue, however, after importing a component, you need to declare it in components because the data used in the template must be hung on this once. 4) Different implementation principles of monitoring data changes

  • With getters/setters and some hijacking of functions, Vue knows exactly how the data is changing and does not require special optimization to achieve good performance
  • React the default was conducted by means of comparative reference, if not optimal (PureComponent/shouldComponentUpdate) may lead to a lot of unnecessary vDOM to render. This is because Vue uses mutable data, while React puts more emphasis on immutable data.

5) Higher-order components

React can be extended through HOC, while Vue needs to be extended through mixins.

High-order components are high-order functions. React components are pure functions themselves, so high-order functions are a piece of cake for React. Instead, vue.js uses HTML templates to create view components, which don’t compile efficiently, so Vue can’t be implemented using HOC.

6) Build tools

Both have their own build tools:

  • React ==> Create React APP
  • Vue ==> vue-cli

7) Cross-platform

  • React ==> React Native
  • Vue ==> Weex

The advantages of Vue

Lightweight framework: Focused only on the view layer, is a collection of views that build data, only tens of KB in size;

Easy to learn: Chinese developed, Chinese documents, there is no language barrier, easy to understand and learn;

Two-way data binding: Preserves Angular features and makes data manipulation easier;

Componentization: React retains the advantages of encapsulation and reuse of HTML, and has unique advantages in building single-page applications.

Separation of view, data and structure: it makes it easier to change the data, without the need to modify the logical code, and only need to operate the data to complete the relevant operations;

Virtual DOM: DOM manipulation is very performance consuming. The native DOM manipulation node is no longer used, which greatly liberates DOM manipulation. However, the specific DOM operation is just changed in another way.

Faster operation: Compared with React, vUE also operates on the virtual DOM. In terms of performance, vue has a big advantage.

What is the difference between assets and static directories?

Similarities: Assets and static both store static resource files. Resource files, images, font ICONS, style files, etc. needed in the project can be placed under these two files.

Similarities: Static resource files stored in assets will be packaged and uploaded when the project is packaged, that is, when NPM run build is run. The so-called simple packaging can be understood as compression volume and code formatting. The compressed static resource file is eventually placed in a static file and uploaded to the server along with index.html. Static resource files do not need to go through the packaging, compression and formatting process, but directly into the packaged directory, directly uploaded to the server. However, static resource files are not compressed, so the volume of the file is larger than that of the packaged assets file. It takes up more space on the server.

Suggestion: Place style files js files required by the template in the project in assets and go through the packaging process. Reduce volume. The imported third-party resource files, such as iconfoont. CSS, can be stored in static because these imported third-party files have been processed and are uploaded directly.

Implement array deduplication

Use some data structures to store non-repeating primitives for de-duplication, such as hash table, that is, ordinary objects; Or you can use the Set Set and then convert it to an array.

/** * the array is deduplicated@param {any[]} arr 
 */
function uniqueArr(arr) {
  if(! arr) {return [];
  }
  return Array.from(new Set(arr));
}

function uniqueArr2(arr) {
  if(! arr) {return [];
  }
  const map = new Map(a); arr.forEach(item= > {
    map.set(item, undefined);
  });
  return Array.from(map.keys());
}
Copy the code

Implement the flat method of arrays

The Flat () method recurses through the array of numbers at a specified depth and returns all the elements in a new array combined with the elements in the traversed subarray.

The flat function takes an argument that represents the structural depth of the extracted nested array, which defaults to 1,

/** * array flattening *@param {number} depth 
 */
Array.prototype.myFlat = function(depth) {
  const res = [];
  depth = depth || 1;
  this.forEach(item= > {
    if(Array.isArray(item) && item.length >= depth) { res.push(... this.myFlat.call(item, depth)); }else{ res.push(item); }});return res;
};
Copy the code

Reference:

  • Array.prototype.flat – MDN

Implement the array push method

Push is simply adding one or more parameters to an array.

Array.prototype.push = function() {
  const arr = arguments.length > 0 ? Array.from(arguments) :undefined]
  arr.forEach(item= > {
    this[this.length] = item;
  });
  return arr.length;
};
Copy the code

Code output results (Promise related)

Code snippet:

async function async1 () {
  console.log('async1 start');
  await new Promise(resolve= > {
    console.log('promise1')})console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start')
async1().then(res= > console.log(res))
console.log('srcipt end')
Copy the code

Look at the use of async and await. Remember that these two keywords are just syntactic sugar and await is equivalent to a promise.then () chain call.

async function async1 () {
  console.log('async1 start'); // 3. Print async1 start
  await new Promise(resolve= > { // 4. Execute new Promise() and print promise1
    console.log('promise1')})console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start') // 1. Print srcipt start
async1().then(res= > console.log(res)) // 2. Run async1
console.log('srcipt end') // 5. Print srcipt end
Copy the code

The printed result is:

srcipt start
async1 start        
promise1
srcipt end
Copy the code

Code snippet:

async function async1 () {
  console.log('async1 start');
  await new Promise(resolve= > {
    console.log('promise1')
    resolve('promise1 resolve')
  }).then(res= > console.log(res))
  console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start')
async1().then(res= > console.log(res))
console.log('srcipt end')

Copy the code

Perform logical analysis:

async function async1 () {
  console.log('async1 start'); // 3. Print async1 start
  await new Promise(resolve= > { // 4. Execute new Promise()
    console.log('promise1')   Print promise1
    resolve('promise1 resolve') // 6. Update the PROMISE state, then callback into asynchronous microtask
  }).then(res= > console.log(res)) Print promise1 resolve, update promise state, await code to enter asynchronous microtask
  console.log('async1 success'); // 9. Print async1 success
  return 'async1 end' // 10. Return a successful Promise with status asynC1 end
}
console.log('srcipt start') // 1. Print srcipt start
async1().then(res= > console.log(res)) // 2. Async1 (); Print async1 end
console.log('srcipt end') // 7. Print srcipt end. The macro task is complete and the micro task starts
Copy the code

Print result:

srcipt start
async1 start        
promise1
srcipt end
promise1 resolve    
async1 success      
async1 end
Copy the code

Flip the binary tree

Input: 4 / \ 27 / \ / \ 1 3 6 9 Output: 4 / \ 7 2 / \ / \ 9 6 3 1Copy the code

Iteratively flip the left and right subtrees.

/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; *} * /
/ * * *@param {TreeNode} root
 * @return {TreeNode}* /
var invertTree = function(root) {
    change(root);
    return root;
};

function change(root){
    if(! root){return;
    }
    const left = root.left;
    const right = root.right;
    root.left = right;
    root.right = left;
    change(left);
    change(right);
}
Copy the code

The sum of three number

Given an array nums containing n integers, determine if there are three elements a, B, and c in nums such that a + b + c = 0. Please find all the triples that sum to 0 and are not repeated. Note: Repeated triples cannot be included in the answer. Input: nums = [1, 2, 1, 4] output: [[1, 1, 2], [1, 1]] : input output nums = [0] : []Copy the code

In order to optimize the solution, we need to find a few key points:

  • Elements in triples are not repeated: the sorted array can be used to traverse the elements, skipping repeated numbers
  • The complexity is reduced to the sum of two numbers, and then all solutions are found using double Pointers
class Solution:
    def threeSum(self, nums: List[int]) - >List[List[int]] :
        n = len(nums)
        # sort first
        nums.sort()
        ans = list(a)# enumeration a.
        for first in range(n):
            Need to be different from the last enumeration
            if first > 0 and nums[first] == nums[first - 1] :continue
            The pointer to # c initially points to the rightmost end of the array
            third = n - 1
            target = -nums[first] # drops to the sum of two numbers
            # enumeration b
            for second in range(first + 1, n):
                Need to be different from the last enumeration
                if second > first + 1 and nums[second] == nums[second - 1] :continue
                Make sure b is to the left of c
                while second < third and nums[second] + nums[third] > target:
                    third -= 1
                # If the Pointers overlap, as b continues to increase
                # there is no c where a+b+c=0 and b
                if second == third:
                    break
                if nums[second] + nums[third] == target:
                    ans.append([nums[first], nums[second], nums[third]])
        
        return ans
Copy the code