Front-end comprehensive interview question 1 (continuously updated)

The difference between Map and Object

ES6 provides a Map class, which is a new data structure, which is a bit like Object

the difference:

Object is essentially a collection of key-value pairs in a hash structure. It can only use simple data types such as strings, numbers, or symbols as keys , which brings great limitations.

The Map class inherits Object and has made some extensions to Object functions. The key of Map can be any data type.

The difference between the two mainly has the following points:

Collision of the same name

We know that the object actually opens up a piece of memory on the heap, and the key of the Map actually stores the address of this piece of memory. As long as the addresses are different, they are two different keys, which solves the collision problem of properties with the same name, which is obviously impossible for traditional Objects.

Iterable

Map implements iterators, which can be traversed with for...of, but Object cannot.

length

Map can get the length directly, but Object cannot.

orderliness

The elements filled in the Map will maintain the original order, but Object cannot.

expandable

Map can be expanded using ellipsis syntax, but Object cannot.

The difference between Map and Set

== Map == is a structure of a set of key-value pairs, with extremely fast search speed. Initializing Map requires a two-dimensional array, or directly initializing an empty Map.

Map has the following methods:

var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined

Since a key can only correspond to one value, a value is placed in a key multiple times,Subsequent values ​​will overwrite previous values

var m = new Map();
m.set('Adam', 67);
m.set('Adam', 88);
m.get('Adam'); // 88

== Set == is also a set of keys, similar to Map. But the difference is that Set does not store value, and its key cannot be repeated . To create a Set, you need to provide an Array as input, or create an empty Set directly:

var s1 = new Set(); // 空Set
var s2 = new Set([1, 2, 3]); // 含1, 2, 3

Duplicate elements will be automatically filtered in the Set** (Note: The number 3 and the string '3' are different elements)**:

var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}

Set has the following methods:

//通过add(key)方法可以添加元素到Set中,可以重复添加,但不会有效果
s.add(4);
s; // Set {1, 2, 3, 4}
s.add(4);
s; // 仍然是 Set {1, 2, 3, 4}

//通过delete(key)方法可以删除元素
var s = new Set([1, 2, 3]);
s; // Set {1, 2, 3}
s.delete(3);
s; // Set {1, 2}


add(value):添加某个值,返回Set结构本身。 
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。 
has(value):返回一个布尔值,表示该值是否为Set的成员。 
clear():清除所有成员,没有返回值。

Summarize:

1. A Map object is a collection of key-value pairs, similar to a JSON object, but the key can be not only a string but also various other types of values, including objects, which can become the key of a Map. The methods are: set get has delete

var map = new Map();
var obj = {
     
      name: '小缘', age: 14 };
map.set(obj, '小缘喵');
map.get(obj); // 小缘喵
map.has(obj); // true
map.delete(obj) ;// true
map.has(obj); // false

2. The Set object is similar to an array, and the values ​​of its members are unique

What are the functions of filter, every, and flat of the array

The role of filter

A new array is created with all elements that meet the criteria

the role of every

Query whether the elements in the array meet the requirements, return true if they are all satisfied, otherwise return false

the role of some

Query whether there are elements in the array that meet the requirements, if they are satisfied, return true and do not continue to execute, otherwise return false

The role of flat

Flatten arrays, such as converting two-dimensional arrays to one-dimensional arrays, and three-dimensional arrays to one-dimensional and two-dimensional arrays. It accepts a parameter, if not passed in, the default is 1, which means the number of layers to be flattened.

ES6 new features

1.let keyword

The let keyword is used to declare variables. Variables declared using let have several characteristics:

  1. Duplicate statement not allowed
  2. block scope
  3. There is no variable hoisting (cannot be used before undefined)
  4. does not affect the scope chain

2. const keyword

The const keyword is used to declare constants. The const declaration has the following characteristics:

  1. declaration must assign an initial value
  2. Identifiers are generally uppercase
  3. Duplicate statement not allowed
  4. Value does not allow modification
  5. block scope

3. Variable deconstruction assignment

ES6 allows to extract values ​​from arrays and objects and assign values ​​to variables according to a certain pattern, which is called destructuring assignment.

//1. 数组的结构
const Hua = ['小花','刘花','赵花','宋花'];
let [xiao, liu, zhao, song] = Hua;
// 结构赋值完,可以直接使用
console.log(xiao);
console.log(liu);
console.log(zhao);
console.log(song);

//2. 对象的解构
const zhao = {
    
    
    name: '赵本山',
    age: '不详',
    xiaopin: function(){
    
    
        console.log("我可以演小品");
    }
};

let {
    
    name, age, xiaopin} = zhao;
console.log(name);
console.log(age);
console.log(xiaopin);
xiaopin();

let {
    
    xiaopin} = zhao;
xiaopin();

4. Template strings

The template string (template string) is an enhanced version of the string, identified by backticks (`), features:

  1. Newline characters can appear in the string
  2. Variables can be output in the form of ${xxx}

5. Simplify object writing

ES6 allows variables and functions to be written directly inside curly braces as properties and methods of objects. This writing is more concise.

6. Arrow functions

ES6 allows the use of "arrows" (=>) to define functions. There are only two ways to write arrow functions, omitting parentheses and omitting braces. (note: it does not have its own this)

Points to note about arrow functions:

  1. If there is only one formal parameter, parentheses can be omitted (omit parentheses)
  2. If the function body has only one statement, the curly braces can be omitted, and the return value of the function is the execution result of the statement (the curly braces are omitted)
  3. Arrow function this points to the value of this in the scope where it was declared
  4. Arrow functions cannot be instantiated as constructors
  5. Cannot use arguments

7.Symbol

  1. Symbol basically uses
    ES6 to introduce a new primitive data type Symbol, which represents a unique value. It is the seventh data type of the JavaScript language and is a data type similar to strings.

Symbol usage scenario: Add properties and methods to objects

Symbol features:

The value of Symbol is unique, which is used to solve the problem of naming conflicts.
Symbol value cannot be operated with other data.
The object properties defined by Symbol cannot be traversed by for...in loop, but you can use Reflect.ownKeys to get all the key names of the object.

注: 遇到唯一性的场景时要想到 Symbol

USONB you are so niubility(JavaScript七种数据类型)

U undefined

S string symbol

O object

N null number

B boolean

8.Promise

Promises are a new solution to asynchronous programming introduced by ES6. Syntactically, Promise is a constructor that encapsulates an asynchronous operation and can obtain its success or failure result.

Promise constructor: Promise (excutor) {}
Promise.prototype.then method
Promise.prototype.catch Exclusive guard:

 //实例化 Promise 对象,成功是resolve,失败是reject
const p = new Promise(function(resolve, reject){
    
    
    setTimeout(function(){
    
    
        // let data = '数据库中的用户数据';
        // resolve(data);

        let err = '数据读取失败';
        reject(err);
    }, 1000);
});

//调用 promise 对象的 then 方法
p.then(function(value){
    
    
    console.log(value);
}, function(reason){
    
    
    console.error(reason);
})

// 发送ajax请求,接口地址: https://api.apiopen.top/getJoke
const p = new Promise((resolve, reject) => {
    
    
    //1. 创建对象
    const xhr = new XMLHttpRequest();
    //2. 初始化
    xhr.open("GET", "https://api.apiopen.top/getJ");
    //3. 发送
    xhr.send();
    //4. 绑定事件, 处理响应结果
    xhr.onreadystatechange = function () {
    
    
        //判断
        if (xhr.readyState === 4) {
    
    
            //判断响应状态码 200-299
            if (xhr.status >= 200 && xhr.status < 300) {
    
    
                //表示成功
                resolve(xhr.response);
            } else {
    
    
                //如果失败
                reject(xhr.status);
            }
        }
    }
})

//指定回调
p.then(function(value){
    
    
    console.log(value);
}, function(reason){
    
    
    console.error(reason);
});

Common Promise Interview Questions

  1. What problem does Promise solve?
  2. What are the industry implementations of Promise?
  3. What are the commonly used APIs for Promise?
  4. Can you write a Promise that conforms to the Promise/A+ specification?
  5. What is the execution process of Promise in the event loop?
  6. What's wrong with Promises, and how can they be fixed?

What problems did you encounter in the project? how to solve it

  1. process token

  2. Data-driven views are not immediate (components are not rendered asynchronously to get DOM elements)

    Solution: use the updated hook functionthis.$nextTick() setTimeOut()

    Want to manipulate DOM immediately Vue is updated asynchronously

    After the data is updated, because the view update is asynchronous, a call is requiredthis.$nextTick(()=>{可以拿到更新之后的DOM})

    Note: If there is a v-if, it cannot be used

  3. Regarding the problem of large numbers of data returned by the backend

    The problem of large numbers in js: (beyond the range of js safe integers)

    The backend returned some id values, and then I used the id value to request the response data, but found that the request was not available, and coordinated with the backend, and found that the id I converted into a numeric value did not match the string id given by the backend

    I have never been able to figure out what caused it. Later, I went to Baidu and found that it was because js could not accurately represent the data exceeding 2 to the 53rd power.

    I went to the backend again and asked him to modify the id, but the backend said it couldn’t be changed

    I can only find a solution by myself, and later found a plug-in to solve this problem:npm i json-bigint

    ①Importimport jsonBig from 'json-bigint'

    ②Convert to value: const obj =jsonBig.parse(JSON数据) obj.property name.toString() —>value

    Large numbers of data to JSON data use JSON.stringify(JSONBig.parse(jsonStr))----->JSON data ----->pass to the backend

The difference and use of Promise.all and Promise.race

Promise.all

For example, when P1 and P2 in the array are all executed, the page is displayed.

It is worth noting that the order of the returned array results will not change , even if the return of P2 is faster than the return of P1, the order is still P1, P2

Promise.all returns success array successfully ,

Failed to return failed data, once failed, it will not continue to go down

        let p1 = Promise.resolve('aaa')
        let p2 = Promise.resolve('bbb')
        let p3 = Promise.reject('ccc')
        let p4 = Promise.resolve('ddd')
        Promise.all([p1, p2, p3, p4]).then(res => {
     
     
            console.log(res); //返回数组
        }).catch(err => {
     
     
            console.log(err);
        })

promise.race()

Promise.race means race, that is to say, whichever result in Promise.race([p1, p2, p3]) is obtained quickly will return the result, regardless of whether the result itself is success or failure

scenes to be used:

When we do an operation, we may 同时need the data returned by different interfaces. In order to consider the order of the returned data, we can usePromise.all

Several servers provide several interfaces 同样的服务. We don’t know which interface is faster, so we can use it Promise.race. Which interface’s data comes back first, we will use which interface’s data.

What is the essence (principle) of v-mode

v-modelThe essence is the syntactic sugar of v-bind:value="" and @input event

When there are value attributes and input custom events on a component at the same time, and the operation is the same variable, you can use v-model to simplify

How to modify the default rule attributes customized by v-model by modelmodifying

 model: {
     
     
    prop: 'isFollowed',
    event: 'changed'
  }

knowledge points

Less syntax: @import ' ';must be quoted

Introduce import in main.js, only comments are allowed between imports and no other statements are allowed

import import rules:

1. The downloaded third-party package: import: 'package name' (go to node_modules to find the index.js file)

2. Manual import: import: './filename'

Push commit:

The meaning of git push -u origin master:

Complete writing: git push --set-upstream origin master:master

Parse:

master: master is to submit the local master to the remote warehouse master branch master

–set-upstream is for each latest or successfully pushed branch, add upstream (tracking) reference abbreviated as -u (simple understanding is to remember this submission information, you can directly git push the next submission)

origin: is the added remote warehouse address

Create an instance:

const request = axios.create ({})

==Advantages: == You can request different servers according to different paths, if written in main.js, the code will appear bloated or this: the axios.defaults.baseURL:path will be directly written to death

Lazy loading:

Benefits: Increase the speed of the first screen Vue is a single page (only one html)

How to improve loading speed?

If the original import method is used, webpack will package all components into a js file when packaging, and load the js when the page is just refreshed

Lazy loading: webpack will package the lazy-loaded components individually into js files one by one, which will be loaded when the user jumps to the corresponding component

Named slots:

New syntax: v-slot must be wrapped with a template tag: the name is abbreviated as #name

Old syntax: slot="name" in specific tags

example:<i slot="名字"></i>

JSON data:

The format of double quotes: attributes and values ​​​​are double quotes

json data does not support undefined and functions

Objects and arrays are converted to json data: JSON.stringfly()the opposite is:JSON.parse

Deep copy:

  • Positive and deserialization (disadvantage: cannot contain undefined and function data)
  • Deep copy through recursion

Encapsulation request parameter passing requirements:

  • If it is directly written as follows in data ①, the parameter passing in the encapsulated function should be ②
//①
data(){
    
    
    return {
    
    
        a:'',
        b:''
    }
}
//②
export const login = (tel,code) => {
    
    
  return request({
    
    
    method: 'POST',
    url: '/v1_0/authorizations',
    data:{
    
    
      mobile:tel,
      code:code
    }
  })
}
  • Shorthand:

Write an object in data and write data to the object as follows:

  data () {
    
    
    return {
    
    
      user: {
    
    
        mobile: '',
        code: ''
      }
    }
  },
  
  
  //
  export const login = data => {
    
    
  return request({
    
    
    method: 'POST',
    url: '/v1_0/authorizations',
    data
  })
}

Token value related knowledge points:

After the first successful login, the server returns the token value

In order to prevent the loss of the refresh token value, the data needs to be backed up to local storagewindow.localStorage.setItem('仓库名字',JSON.stringify())

Notice:Local storage can only store string format JSON.stringify()serialization

That is, serialize when storingJSON.stringify()

Deserialize when fetchingJSON.parse

The difference between vuex and local storage:

vuex: ① vuex is responsive data ② temporary storage

local storage:

sessionStorage: life cycle - the browser closes the data disappears, refreshes the data does not disappear, the data is shared by the current page, the memory is 5M, and the stored data is JSON data

localStorage: lifecycle-permanent, same browser data sharing (same domain name, must be same host name), memory size 20M, stored data is JSON data

How is the token stored in your project?

1. Save vuex first 2. Save local storage

The destructured attribute name must be the same as the attribute name in the response {data}

Password encryption (md5.js)

If the backend needs password encryption, you need to download this plugin

How to do aging processing of local storage?

①Save token—>additional timestamp ( timer: +new Date() )

②When using token, first get the current timestamp - timestamp in storage / 1000 / 60 (minutes) > time difference

③If it times out, jump to the page to let the user log in again. If there is no timeout, use the token normally

css in vue uses image path:background: url("~@/assets/banner.png");

Routing jump:

Both name and path are routing jumps, but name is better maintained

Click on the login to jump to another page Programmatically: @click="$router.push('/login')" this is the shorthand method

Specifically written:

this.$router.push({
    path:'/login',
    ...需要传递的参数
})

You need to go back to another page after the jump: $router.back()or: $router.go(-1)-1 to go back once

There is no need to write this in the difference expression

What is a Single Page Application (SPA):

One of the core ideas of Single Page Application (SPA) is to update the view without re-requesting the page. Simply put, when loading the page, it will not load the entire page, but only update the content in a specified container. For most single-page applications, the officially supported vue-router is recommended.

Among them, NetEase Music uses a single-page application

Vue's routing implementation mode: hash mode and history mode

hash mode:

Vue-router defaults to hash mode, which uses the hash of the URL to simulate a complete URL. When the URL changes, the page will not reload. # is the hash symbol, the Chinese name is the hash symbol or anchor point, and the value after the hash symbol is called the hash value.

The hash mode of the route is realized by using the window to listen to the onhashchange event, that is to say, the hash value is used to guide the browser's actions and has no effect on the server. The HTTP request will not include the hash value, and each time the hash is changed Value, will add a record in the browser's access history, use the "Back" button, you can return to the previous position. Therefore, the hash mode changes according to the hash value, and renders different data at the specified DOM position according to different values.

history mode:

The URL in the hash mode will have a # sign, which affects the appearance of the URL, but the # sign will not appear in the history mode. This mode makes full use of history.pushState() to complete the URL jump without reloading the page.When using the history mode, you need to add mode:'history' to the routing rule configuration, the example code is as follows:

// main.js 文件
const router = new VueRouter ({
    
    
    mode:'history',
    routes: [...]
})

There are two new APIs for history in HTML5, namely history.pushState()andhistory.replaceState() Can modify the browser history stack, and popState event listeners to state changes.

They all receive 3 parameters, namely state object (state object), title (title) and address (URL). Below we briefly introduce the meaning of these three parameters.

(1) State object (state object): A JavaScript object associated with a new history entry created with the pushState() method.

(2) title (title): FireFox browser currently ignores this parameter. For security reasons, it is recommended to pass an empty string. Alternatively, a short title can be passed in, indicating the state to enter.

(3) Address (URL): the address of the new history entry.

What is the vue family bucket? What are there?

Vue family bucket generally refers to scaffolding vue-cli, routing vue-Router, state management mode vuex, Axios, elementUI and other ui frameworks and packaging tools webpack

command package:

npm i -g nrm — switch mirror sources

npm ls view

npm i package

or npm i -g cnpm

How to access vuex data in js file?

Import the store of the vuex warehouse

Request interceptor:

Function: uniformly inject the request header token into the authorized interface

Add a judgment condition:

If the user is not logged in, the token value is null and an error is reported, so add a judgment condition if(user && user.token){} === if(null && null.token) and if it is null, exit the judgment condition

Add the headers request header in the config configuration item

After adding headers to the request interceptor, you can comment out the headers in api/user.js

Insensitive refresh (response interceptor)

Short token: used to send requests, carried in the request header, usually expires in two hours

refresh_token: The long token is used to obtain a new short token, which usually expires in 14 days

Can the expiration time of the short token be extended, such as 14 days?

Answer: No, because it involves security issues, to prevent the token from being stolen (only if the two are stolen together will the information be leaked) we can encrypt the login password—md5.js encryption, (MD5 encryption is essentially a plug-in, calling his method The encrypted code can be generated) We need to cooperate with the backend (backend decryption)

Ideas for using long tokens:

  1. When the user sends a request, the backend returns 401, indicating that the token expires. At this time, the 401 code returned by the backend should be uniformly monitored.

  2. When a 401 error is detected, refresh_tokensend a request with a long token to obtain the latest token

  3. Automatically resend the request sent by the user last time

  4. Add response interceptor

    • main effect:
      • Refresh without feeling
      • Unified processing of the data returned by the backend
      • Unified processing of back-end data errors

Ideas for using long tokens (specific steps):

  1. When the user sends a request, if the backend returns 401, it means that the token has expired. At this time, we need to uniformly monitor the 401 code returned by the backend.

    • We need to add a response interceptor, and monitor and judge whether the token expires in the error reporting function in the interceptor. The code is as follows:

      if (error.response.status === 401) {
              
              
               console.log('token过期')
      }
      
  2. When a 401 error is detected, refresh_tokensend a request with a long token to obtain the latest token

    • Note: you can’t use request to send, 会死循环because the request is set with a request interceptor, and the old token will be injected (provided that you encapsulate the request yourself). The code example is as follows:

      // 用axios发请求
          const {
              
               data } = await axios({
              
              
            url: 'http://toutiao.itheima.net/v1_0/authorizations',
            method: 'PUT',
            headers: {
              
              
              Authorization: `Bearer ${
                
                store.state.token.refresh_token}` /* 怎么拿refresh_token */
            }
          })
      
  3. Then use the new token to save it in vuex and save it to local storage. You cannot use auxiliary functions in the js file, and use destructuring assignment to overwrite the old token. The code is as follows:

     store.commit('setUser', {
          
           ...store.state.token, token: data.data.token })
    
  4. Automatically resend the request sent by the user last time

    return request(error.config)
    

The complete code is as follows:

// 添加响应拦截器
request.interceptors.response.use(function (response) {
    
    
  // 2xx 范围内的状态码都会触发该函数。
  // 对响应数据做点什么
  return response
}, async function (error) {
    
    
  /* //监测token过期 */
  if (error.response.status === 401) {
    
    
    // console.log('token过期')
    // 发请求,刷新token
    // 注意:不能用request发,会死循环,因为request设置了请求拦截器,会注入老token
    // 用axios发请求
    const {
    
     data } = await axios({
    
    
      url: 'http://toutiao.itheima.net/v1_0/authorizations',
      method: 'PUT',
      headers: {
    
    
        Authorization: `Bearer ${
      
      store.state.token.refresh_token}` /* //怎么拿refresh_token */
      }
    })
    // 新token存到vuex中,存到本地存储,在js文件中不能用辅助函数
    // 利用解构赋值覆盖旧token
    store.commit('setUser', {
    
     ...store.state.token, token: data.data.token })
    // 再发一次上次发送过得请求(error里有上一次发送的地址和错误的token)
    return request(error.config)
  }
  // 超出 2xx 范围的状态码都会触发该函数。
  // 对响应错误做点什么
  return Promise.reject(error)
})

To modify the global foreign component style in the component, you need to add /deep/ (must be less syntax) (use ::v-deep in scss syntax)

JSON.parse() is deserialization, which converts a string in json format into an object (the string in json format must be in double quotes, and its attributes and values ​​are wrapped in double quotes) JSON.parse('sfdsfsa'). The quotation marks are the wrong json format and an error will be reported

Why do list scrolls affect each other?

Because they are not scrolling within themselves, but the entire body page is scrolling.

Remember the scroll position of the list:
Method:
Let each label content article list generate its own scrolling container, so that it will not affect each other

How to generate your own scrolling container for the article list:
set a fixed height, height: xxx; (if there is no effect, you can consider using the viewport unit vh, vw, they are not affected by the parent)

.article-list {
    
    
height: xxx ;
overflow-y:auto;  //垂直溢出滚动
}

Add data using destructuring:

this.list = [...this.list, ...data.data.results] Append new data to the end

Add height tips to label content

Set the height for partial content, which can be adapted to any device

height: calc(100vh - 274px);
  overflow-y: auto;

How are filters used globally and locally?

After configuring the global dayjs, you must export it if you want to use it globally

Pulling down to refresh the data will encounter blank space:

This is because the data is not enough, the data cannot support the height of the content

Solution: Need to fill the height of the content with the data

How to handle relative time

Day.js (opens new window) is a lightweight JavaScript library for handling time and date, and the API design of Moment.js (opens new window) remains exactly the same

  1. Install
npm i dayjs
  1. Create utils/dayjs.js
import Vue from 'vue'
import dayjs from 'dayjs'

// 加载中文语言包
import 'dayjs/locale/zh-cn'

import relativeTime from 'dayjs/plugin/relativeTime'

// 配置使用处理相对时间的插件
dayjs.extend(relativeTime)

// 配置使用中文语言包
dayjs.locale('zh-cn')

// 全局过滤器:处理相对时间
Vue.filter('relativeTime', value => {
     
     
  return dayjs().to(dayjs(value))
})
  1. Load initialization in main.js
import './utils/dayjs'
  1. use
<span>{
     
     {
     
      article.pubdate | relativeTime }}</span>

expandHow to use locally in components

First of all, the configured dayjsexport by default

export default dayjs

Then import it in the component:

// 组件内使用过滤时间的插件
import dayjs from '@/utils/dayjs'

Then define the function that handles relative time in methods:

methods: {
     
     
    relativeTime (value) {
     
      // value就是管道符前面的数据
      return dayjs().to(dayjs(value)) //to为多少年前
    }
  }

Finally use relative time functions where needed:

<span>{
     
     {
     
      article.pubdate | relativeTime }}</span>

Computed property:

Computed properties will observe changes in internal dependent data, and if the dependent data changes, the calculated properties will be re-executed

Modify the data of the parent component with the sync modifier

Subassembly:

Modify the data of the parent component with the sync modifier

this.$emit('update:active', index)

parent component:

:actives.sync="active"

Note: updateThe attribute

this.$parent:

All data and methods of the parent component can be accessed in the current set

Expand knowledge points:

  1. .sync modifier: When the data is passed from parent to child, the child component can modify the data of the parent component. Parent
    component: :property name.sync = "basic data type" Subcomponent: ①props: {property name} Receive ②Modify the corresponding data of the parent component this.$emit('update:属性名', 要修改的值)(NoticeYou cannot use sync to operate complex data types, such as: arrays, objects)
  2. this.$parent can access all the data of the parent component in the current component, including methods, and can implement the function of modifying the data of the parent component in the child component, and can also call the method of the parent component
  3. this.$children is an array, you can get all parent-child components of the current component
  4. this.$refs ① can take DOM elements ② can also take components

What optimization needs to be done for the search box?

  1. Anti-shake: continuous output event, only executed once (last time), core timer, each event triggers 1 to clear the previous timer
  2. Search history optimization: The searched content is saved to the local storage. Every time the user searches, the searched keyword is first checked from the local storage. If there is a keyword, it is directly accessed from the local storage. If not, a request is made to render the data.

The post and get request methods with parameters of axios are quite different.

The GET request with parameters isparams

The POST request with parameters isdata

PATCH toodata

PUT is alsodata

adaptation:

adaptive, responsive

Adaptive Technology:

1. Switch html font-size + rem through media query

Disadvantages: to write a lot of media queries, cumbersome

2. Mobile Taobao flexible.js + rem flexible.js monitors the screen size change through js (via the onresize event), **core algorithm: **html font-size=screen width/10

3. vw/vh adaptive screen width height viewport width/10 (viewport unit)

Use postcss-pxtorem (opens new window) to convert px to rem:will not convert inline styles

rem calculation principle: (element pixel)px / root font size=rem

rem adaptation principle (important)

Target:Realize the equal scaling effect of web page element sizes on devices with different widths

rem unit size

  1. Set different HTML tag font sizes according to viewport width
  2. Write the code, the size is rem unit
    • Determine the font size of the HTML tag (basic root font size) of the device corresponding to the design draft
    • Check the width of the design draft → determine the reference device width (viewport width) → determine the reference root font size (1/10 viewport width)
    • Dimensions in rem units (N is rem)
      • N * 37.5 = 68 → N = 68 / 37.5
      • The size of rem unit = px unit value / base root font size
    • The size of the rem unit = px unit value / base root font size (the result takes 3 decimal places)

(The design draft is 750px. Divide a line into 10 parts, and 1 part is 75. Generally speaking, the design draft of 750 should be divided by 2 to be 375 and then divided by 10. One part is 37.5)

Principle of Vue

1. Component basis => (MVVM model)

Traditional components, knowledge static rendering, update depends on manipulating DOM.

The core concept of Vue is the concept of data-driven, the so-called data-driven concept: when the data changes, the user interface will also change accordingly, and developers do not need to manually modify the dom.

advantage:

    不需要在代码中去频繁的操作dom了,这样提高了开发的效率,同时也避免了在操作Dom的时候出现的错误。

The data drive of Vue.js is realized through the framework of MVVM. The MVVM framework mainly includes three parts: Model, View, ViewMode

Data Driven View - Vue MVVM

MVVM is the abbreviation of Model-View-ViewModel, which is to evolve the Controller in MVC into ViewModel. Model represents the data model, View represents the UI component,ViewModel is the bridge between the View and Model layers. Data will be bound to the ViewModel layer and automatically render the data to the page. When the view changes, the viewModel layer is notified to update the data.

2. Responsive principle of Vue

Core implementation class:

Observer: Its function is to add getters and setters to the properties of the object for dependency collection and dispatch updates.
Dep : Used to collect the dependencies of the current responsive object, each responsive object including sub-objects has a Dep instance (in which subs is an array of Watcher instances), when the data changes, each will be notified through dep.notify() watcher.
Watcher: Observer object, instance is divided into rendering watcher (render watcher), calculated attribute watcher (computed watcher), listener watcher (user watcher) three kinds of
relationship between Watcher and Dep,
dep is instantiated in watcher and sent to dep.subs Subscribers are added, and dep traverses dep.subs through notify to notify each watcher of updates.

When relying on collection (getter)
initState, when the computed attribute is initialized, the computed watcher is
triggered. When relying on collection initState, when the listener attribute is initialized,
the process of user watcher dependency collection render() is triggered, and when the render watcher dependency collection
re-render is triggered, When vm.render() is executed again, the subscription of watcher in all subs will be removed and reassigned.
The dispatch update (setter)
component modifies the response data, triggers the logic of the setter,
calls dep.notify()
to traverse all subs (Watcher instances), and calls the update method of each watcher.

principle:

    当创建 Vue 实例时,vue 会遍历 data 选项的属性,利用 Object.defineProperty 为属性添加 getter 和 setter 对数据的读取进行劫持(getter 用来依赖收集,setter 用来派发更新),并且在内部追踪依赖,在属性被访问和修改时通知变化。

    每个组件实例会有相应的 watcher 实例,会在组件渲染的过程中记录依赖的所有数据属性(进行依赖收集,还有 computed watcher,user watcher 实例),之后依赖项被改动时,setter 方法会通知依赖与此 data 的 watcher 实例重新计算(派发更新),从而使它关联的组件重新渲染。

Object.defineProperty implements responsiveness

Listener object, listener array
complex object, deep listener

const obj = {
    
    };
const data = {
    
    };
const name = 'zhangsan';
Object.defineProperty(data, 'name', {
    
    
    get: function () {
    
    
        console.log('get');
        return name;
    },
    set: function (newVal) {
    
    
        console.log('set');
        obj.name = newVal;
    }
})
console.log(data.name);
data.name = 'lisi';
console.log(obj.name);  

Disadvantages of Object.defineProperty

In-depth monitoring needs to be recursive to the end, and the amount of calculation is large at one time.
It is impossible to monitor new attributes and delete attributes (use Vue.set Vue.delete)
and cannot natively monitor arrays, which requires special processing [Rewrite the method of the array, ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'] These methods only change the array in a responsive manner, directly changing the index will not change in a responsive manner]

Summarize:

Vue双向数据绑定的原理:
vue.js 采用数据劫持结合发布-订阅模式,通过 Object.defineproperty 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发响应的监听回调。    
    

The principle of Vue two-way data binding(important)

We all know that Vueit is a framework for two-way binding of data, and two-way binding consists of three important parts

  • Data layer (Model): application data and business logic
  • View layer (View): the display effect of the application, various UI components
  • Business logic layer (ViewModel): the core of framework encapsulation, which is responsible for associating data with views

The above layered architecture solution can be called in a professional term: the MVVMcore function of the control layer here is "two-way data binding". Naturally, we only need to understand what it is to learn more about the principle of data binding

Understanding ViewModels

Its main responsibilities are:

  • Update view after data changes
  • Update data after view changes

Of course, it also has two main parts

  • Listener (Observer): monitor the properties of all data
  • Parser (Compiler): scan and parse the instruction of each element node, replace the data according to the instruction template, and bind the corresponding update function

Vue implements two-way data binding by usingData hijacking and the publisher-subscriber pattern. Data hijacking is to use the ES5 Object.defineProperty(obj,key,val)method to hijack the getter and setter of each attribute in the data option, and publish a message to the subscriber when the data changes, thereby triggering the corresponding callback to update the view

In short, when creating a Vue instance, data hijacks the incoming data. At the same time, when the view is compiled, create a Watcher object for the place where the data in the data is used, and then add it to the publisher object in the getter of the data hijacking , when the hijacked data changes, it will notify all observers to operate the DOM to update through the publish-subscribe mode and callback function, thereby realizing the two-way binding of data.

/**
 * 对Object.defineProperty()进行封装
 */
function defineReactive(obj, key, value) {
     
     
    //递归 - 对象的属性仍是对象
    observe(value);
    //变化侦测
    Object.defineProperty(obj, key, {
     
     
        get() {
     
     
            return value;
        },
        set(newVal) {
     
     
            if (newVal !== value) {
     
     
                updateView();
                value = newVal;
                observe(newVal)
            }
        }
    })
}

/**
 * 对一个对象所有属性的变化侦测
 */
function observe(target) {
     
     
    //非对象,直接返回
    if (typeof target !== 'object') {
     
     
        return target;
    }
    //将每个属性转换为getter和setter形式
    for (let key in target) {
     
     
        defineReactive(target, key, target[key])
    }
}
//模拟更新视图的方法
function updateView() {
     
     
    console.log("更新视图");
}

Detect changes in object properties by calling observe directly

existing problems

  1. poor performance
  2. Added property on object cannot be detected
  3. Changing the length property of an array cannot be detected

When creating a Vue instance, Vue will traverse the properties of the data option, use Object.defineProperty to add getters and setters to the properties to hijack the reading of data (getters are used to collect dependencies, setters are used to dispatch updates), and track dependencies internally , notifies changes when properties are accessed and modified.

Each component instance will have a corresponding watcher instance, which will record all dependent data attributes during component rendering (dependency collection, as well as computed watcher, user watcher instance), and then when the dependency is changed, the setter method will notify The watcher instance that depends on this data is recalculated (dispatches updates), so that its associated components are re-rendered.

Record mouse scroll position

The first-level route jump will be destroyed and rebuilt. It is necessary to App.vuepackage the cache component for the first-level route <keep-alive> . Two hook functions will be triggered, namely activated anddeactivated

Can be guarded by navigation within the componentbeforeRouteLeave

// 离开这个组件的路由导航守卫
  beforeRouteLeave (to, from, next) {
    
    
    // 跳走的时候获取组件的滚动位置
    this.top = this.$refs.article[this.active].$el.scrollTop
    next()
  },
  // 缓存组件激活触发的钩子函数
  activated () {
    
    
    if (this.$refs.article) {
    
    
      this.$refs.article[this.active].$el.scrollTop = this.top
    }
  }

The browser's event loop (the execution mechanism of JS)

The event loop in the browser involves the concept of a task queue . After all asynchronous tasks are executed, the corresponding callback functions will be placed in the task queue , and queued for sequential processing . The task queue is divided into a macro task queue and a micro task queue , and only when the call stack of the main thread is cleared, the tasks in the task queue will be executed , which is the so-called JavaScript operating mechanism .


Browser macro tasks mainly include setTimeout() and setInterval() .
Browser microtasks mainly include Promise.then() , requestAnimationFrame(), process.nextTick .

And microtasks have higher priority than macrotasks . When the main thread call stack is idle , it will detect whether there are tasks to be executed in the task queue . First, check whether there are tasks to be executed in the microtask queue. If so, execute the tasks in the microtask queue until the microtask queue is emptied. , and then start to execute the tasks in the macro task queue. After the macro task is cleared, it will then check whether there are tasks in the micro task queue, and so on and so forth to formevent loop

The first event loop

  • First judge whether JS is synchronous or asynchronous, synchronously enters the main thread, and asynchronously enters the event table (in the host environment)
  • The asynchronous task registers the function in the event table, and when the trigger condition is met, it is pushed into the event queue (task queue)
  • After the synchronous task enters the main thread, it will be executed until the main thread is idle, and then it will go to the event queue to check whether there is an executable asynchronous task, and if there is, it will be pushed into the main thread

The above three steps are executed in a loop, which is the event loop

The second type of event loop

 setTimeout(function(){
     
     
     console.log('A')
 });
 
 new Promise(function(resolve){
     
     
     console.log('B');
     for(var i = 0; i < 10000; i++){
     
     
         i == 99 && resolve();
     }
 }).then(function(){
     
     
     console.log('C')
 });
 
 console.log('D');

The result of the above code execution is:B D C A

Analyze the reason why the execution sequence is like this?

This is because asynchronous tasks are divided into macro tasks and micro tasks

  • macro-task (macro task): including the overall code script, setTimeout, setInterval
  • micro-task (micro-task): Promise.then, process.nextTick
  • According to this classification method: the execution mechanism of JS is:
  • Execute a macro task, if a micro task is encountered during the process, put it in the [event queue] of the micro task
  • After the current macro task is executed, it will check the [Event Queue] of the micro task, and execute all the micro tasks in it sequentially

Repeat the above 2 steps, combined with event loop(1) event loop(2), it is more accurateJS execution mechanismup.

The specific execution process is analyzed as follows:

首先执行script下的宏任务,遇到setTimeout,将其放到宏任务的【队列】里

遇到 new Promise直接执行,打印"B"

遇到then方法,是微任务,将其放到微任务的【队列里】

遇到同步任务console.log('D') 直接打印 "D"

本轮宏任务执行完毕,查看本轮的微任务,发现有一个then方法里的函数, 打印"C"

到此,本轮的event loop 全部完成。


下一轮的循环里,先执行一个宏任务,发现宏任务的【队列】里有一个 setTimeout里的函数,执行打印"A"

So the execution result is:B D C A

Consider a complex example:

console.log('1');
setTimeout(function() {
    
    
 
 
console.log('2');
process.nextTick(function() {
    
    
 
console.log('3');
 
 
})
new Promise(function(resolve) {
    
    
 
console.log('4');
resolve();
}).then(function() {
    
    
 
console.log('5')
})
})
//1 2 4 3 5 

Implementation process:

1. Macro task synchronization code console.log('1')

2. setTimeout, add macro task Event Queue, no micro task is found, the first round of event loop is finished

3. The second round of event loop starts, the macro task is executed first, and the callback function of setTimeout is read from the macro task Event Queue

4. Synchronize code console.log('2'), find process.nextTick, add microtask Event Queue

5. New Promise, execute console.log('4') synchronously, find then, add microtask Event Queue

6. After the macro task is executed, the micro task is executed next, first execute process.nextTick, and then execute Promise.then

7. After the microtask is executed, the second round of event loop is completed, no macrotask is found, and the event loop ends

Summarize

The event loop executes the macrotask first, and the synchronous task is executed immediately, the asynchronous task is loaded into the corresponding Event Queue, and the microtask is also loaded into the corresponding Event Queue of the microtask. After all the synchronous microtasks are executed, if the microtask is found There are unfinished tasks in the Event Queue, and executing them first is considered to complete a round of event loop. Next, check whether there is asynchronous code in the queue of the macro task, and if so, execute the second round of the event loop, and so on.

SQL basic syntax

-- SELECT * FROM my_db_01.users;
-- 1.查询整个表所有的数据
-- select * from users
-- 2.查询具体的字段名字
-- select username,password from users
-- 3.查询id是1的这个字段 查询的条件写在where后面
-- select * from users where id=1
-- 4.查询users表里username这个字段 模糊查询 Z%表示以z开头的 %Z写在后面后面表示以z结尾的
-- select * from users where username like 'Z%'
-- 5.条件查询
-- select username,password from users where id>1 and status=0
-- 6.排序 desc(降序) asc(升序)
-- select * from users order by id desc
-- select * from users order by id asc
-- 7.添加
-- insert into users(username,password,status) values('zl',111,1)
-- 8.删除
-- delete from users where id=3
-- 9.修改(更新)update 表明 set 字段属性(多个字段用英文逗号隔开) where (修改的字段对应的id) 如果没有where 将修改整个表
-- update users set username='zs',password=555 where id=1
-- 10.函数count(*)
-- select count(*) from users where status=0

What is the difference between watch, methods and computed?

From the mechanism of action:

  1. methods, watch and computed are all function-based, but each is different
  2. Both watch and computed are based on Vue's dependency tracking mechanismYes, when a certain data changes, all "related" data that depends on this data will "automatically" change, that is, automatically call related functions to realize the data change
  3. For methods: methods are used to define functions, which need to be called manually to be executed. Unlike watch and computed, which "automatically execute" pre-defined functions, compared to watch/computed, methods do not process data logic relationships, but only provide callable functions

In nature:

  1. The functions defined in methods still need to be called.
  2. Computed is a computed attribute , in fact, it is of the same type (used) as the data attribute in the data object.
  3. **watch: **similar to listening mechanism + event mechanism

The difference between watch and computed

  1. Functionally: computed is a computed attribute, watch is to monitor a value change, and then execute the corresponding callback.
  2. Whether to call the cache: the attributes on which the functions in computed depend have not changed, so when the current function is called, it will be read from the cache, and the watch will execute the callback every time the monitored value changes.
  3. Whether to call return: the function in computed must use return to return , the function in watch does not have to use return
  4. Scenarios that watch is good at handling: one data affects multiple data-------search box.
  5. Scenarios that computed is good at handling: one data is affected by multiple data – usage scenarios: when a value is affected by multiple attributes -------- shopping cart product settlement

**watch: ** attribute monitoring

  1. The function name in watch must be consistent with the attribute name in data, because watch depends on the attribute in data, when the attribute in data changes, the function in watch will be executed.
  2. The function in watch has two parameters, the former is newVal and the latter is oldVal.
  3. The functions in watch do not need to be called.
  4. watch will only monitor whether the value of the data changes, but not whether the address of the data changes. That is to say, if watch wants to monitor the changes of reference type data, it needs to perform in-depth monitoring. "obj.name"(){}------If obj has too many attributes, the efficiency of this method is very low, obj:{handler(newVal){},deep:true}------ Use the handler+deep method for in-depth monitoring.
  5. In special cases, the watch cannot monitor changes in the array. In special cases, when the data in the array is changed, the array has changed, but the view has not been updated. To change an array, you must use splice() or set. this . arr . splice ( 0 , 1 , 100 ) − − − − − Modify the data starting from item 0 in arr to 100, this . set. this.arr.splice(0,1,100)-----Modify the data starting from item 0 in arr to 100, this.setthis.arr.splice(0,1,100)Modify the 1 data starting from item 0 in a r r to 1 0 0 , t h i s .set ( this.arr , 0,100)-----modify the value of item 0 in arr to 100.
  6. immediate: true Do a listener when the page is first loaded.
  7. One data affects multiple data - application scenarios: search box, form input, asynchronous update, animation
  8. If you are listening to complex data types, you need to enable deep monitoringdeep:true

computed: computed properties

  • Cached calculations are performed according to dependencies and updated only when needed.
  • A computed property can complete various complex logics and finally return a result; a computed property can depend on the data of multiple vue instances, as long as any one of the data changes, the computed property will be re-executed and the view will be updated. In addition to this, computed properties can depend on other computed properties and data from other instances
  • One piece of data is affected by multiple pieces of data - the settlement of the shopping cart is affected by the quantity of the unit price and whether it is selected

The difference between HTTP and HTTPS (must)

Many people always think that http is https. In fact, there is a big difference between http and https. Let's take a look at the difference between https and http.

One: Let me talk about what is https and http

httpsIt is a secure version of http, also known as hypertext secure transmission, with an encrypted transmission protocol channel, and SSL provides a secure encryption basis, which is used for http transmission.

httpIt is an ordinary hypertext transfer protocol. On the Internet, all files must abide by this HTTP protocol, and its function is to realize the mutual request between the client and the server.

Two: Then what is the difference between https and httpthe difference

The difference between https and http:

**1. **The port of https is 443, while the port of http is 80, and the connection methods of the two are different. The connection of http is very simple and stateless; the HTTPS protocol is constructed by the SSL+HTTP protocol and can be encrypted Network protocols for transmission and identity authentication;

**2. **The HTTP protocol sends content in plain text, without any form of data encryption . For example: if a hacker intercepts the transmission message between the web browser and the website server, he can directly read the content in it. Therefore, the HTTP protocol is not suitable for transmitting some sensitive information, such as payment information such as bank card number and password. , in order to solve this defect of the HTTP protocol, HTTPS adds the SSL protocol on the basis of HTTP, and encrypts the communication between the browser and the server. The reason why the HTTPS protocol is secure is that the HTTPS protocol encrypts the transmitted data, and the encryption process is realized by asymmetric encryption.

**3. **HTTPS needs to go to CA to apply for a certificate, but http does not.

What is the difference between https and http

What is an SSL certificate? (expand)

Because the HTTP protocol sends content in clear text, it is very unsafe to use the HTTP protocol to transmit private information. In order to ensure that these private data can be encrypted and transmitted, Netscape designed the SSL protocol to encrypt the data transmitted by the HTTP protocol, so that HTTPS was born. where S stands for security. security

An SSL certificate is a type of digital certificate, similar to an electronic copy of our driver's license. Because it is configured on the server, it is also called an SSL server certificate.effectIt is used to protect network transactions, data transmission and login. So SSL has gradually become a specification (just like ECMAscript is the specification of js grammar)

The principle of nextTick

Since the Vue DOM update is performed asynchronously, that is, when the data is modified, the view will not be updated immediately, but will monitor the data change and cache it in the same event loop. After all the data changes in the same data loop are completed, they will be unified. The view updates. In order to ensure that the updated DOM is obtained, Vue.nextTick()the method .

There is a special API in vue, nextTick. According to the official documentation, it can execute a callback after the DOM is updated

Although the MVVM framework does not recommend accessing the DOM, sometimes there is such a need, especially when working with third-party plug-ins, DOM operations are unavoidable. And nextTick provides a bridge to ensure that we are operating the updated DOM.

Application scenario:

  • The DOM operation performed in the created() hook function of the Vue life cycle must be placed in the callback function of Vue.nextTick()
    • **Reason:** is that created()the DOM is not actually rendered when the hook function is executed.
  • When an operation to be performed after the data changes, and this operation needs to use the DOM structure that changes with the data change, this operation should be placed in the Vue.nextTick()callback function.
    • Reason : Vue performs DOM updates asynchronously. As long as data changes are observed, Vue will open a queue and buffer all data changes that occur in the same event loop. If the same watcher is triggered multiple times, it will only be pushed into the queue once.

Summarize

The above is the implementation principle of vue's nextTick method, and the summary is:

  1. Vue uses asynchronous queues to control DOM updates and nextTick callbacks to be executed successively
  2. Due to its high priority feature, microtask can ensure that the microtasks in the queue are executed before an event loop
  3. Because of compatibility issues, Vue had to do a downgrade from microtask to macrotask

The principle of module drag and drop

The drag and drop function is mainly used to allow users to do some custom actions, such as drag sorting , drag and move pop-up boxes , etc., the effect is quite good. Let's talk about the principle of drag and drop:

1. Drag and drop process action

①Mouse down
②Mouse move
③Mouse release

here toNotice: The movement event should be written inside the press event

2. Corresponding JS events in the drag and drop process

①When the mouse is pressed, the onmousedown event will be triggered

②Mouse movement will trigger the onmousemove event

③The onmouseup event will be triggered when the mouse is released

3. Explanation of the principle of realization

Drag and drop is actually achieved by obtaining the moving distance of the mouse, that is, calculating the difference between the coordinates (x, y) of the position before the movement and the coordinates (x, y) of the position during the movement.
When the mouse is pressed or the mouse is moved, the current mouse position can be obtained, that is, the position before the movement and the position during the movement.

Another point is that the style of the dragged element must be set to an absolute or relative position to have an effect.

Summarize:

①Principle of dragging in the page: press and move the mouse, then release the mouse

②The trigger event is the mouse is pressed mousedown, the mouse is moved and mousemove the mouse is releasedmouseup

③Drag and drop process: During the mouse movement process, the latest value is obtained and assigned to the left and top values ​​of the modal box, so that the modal box can follow the mouse

④The coordinates of the mouse on the page minus the coordinates of the mouse in the box is the real position of the modal box.

⑤When the mouse is pressed, we need to get the coordinates of the mouse in the box.

⑥ When the mouse moves, let the coordinates of the modal box be set to: The coordinates of the mouse on the page minus the coordinates of the box. Note that the movement event is written in the press event .

⑦When the mouse is released, the dragging will stop, which means that the mouse movement event can be canceled

core code

 		// 鼠标按下获取鼠标在盒子内的坐标
        obj.addEventListener('mousedown', function(e) {
     
     
          //获取鼠标在盒子中的坐标=鼠标在页面中的坐标减去盒子在页面中的坐标  
            var x = e.pageX - box.offsetLeft
            var y = e.pageY - box.offsetTop
                // 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top值
                // 在全局页面中拖拽时要用document,如果用了obj,事件会来不及触发,导致鼠标脱离
            document.addEventListener('mousemove', move)
		function move(e) {
     
     
            box.style.left = e.pageX - x + 'px'
            box.style.top = e.pageY - y + 'px'
        }
        // 鼠标弹起,就让鼠标移动事件移除
        document.addEventListener('mouseup', function() {
     
     
            document.removeEventListener('mousemove', move)
        })

memory leak

What is a memory leak

When the application no longer needs to occupy memory, for some reason, the memory is not reclaimed by the operating system or the available memory pool, which is called a memory leak

Which operations can cause memory leaks

1. Memory leaks caused by global variables
2. Memory leaks caused by closures
3. Forgotten timers or callbacks
4. When the dom is emptied or deleted, memory leaks caused by events not being cleared
5. Repeated rewriting of the same property will cause A large amount of memory is occupied (but the memory will be released after closing IE)

6. If the first parameter of setTimeout uses a string instead of a function, it will cause a memory leak

Solutions to JS memory leaks

1. Pay attention to program logic and avoid "dead loop" and the like.
2. Reduce unnecessary global variables, or objects with a long life cycle, and timely garbage collect useless data.
3. Avoid creating too many objects Principle: no Things that have been lost must be returned in time

What exactly does the new operator do?

1. Create an empty object
2. this points to this new object
3. Execute the code in the constructor to add properties and methods to the new object
4. Return a new object: judge the return value, use the returned object, and create it if there is no an object

The difference between heap and stack

  • Stack area (stack): automatically allocated and released by the compiler, storing function parameter values, local variable values, etc. its mode of operationSimilar to a stack in a data structure.
  • Heap area (heap): generally allocated and released by the programmer. If the programmer does not release it, it may be recycled by the operating system at the end of the program.It is different from the heap in the data organization, the allocation method is similar to a linked list.

their difference

1 How to apply

  • Stack: automatically allocated by the system . For example, when declaring a local variable int b of a function, the system automatically creates space for b in the stack.
  • Heap: The programmer needs to apply for it by himself and specify the size. In C, use the malloc function; in C++, use the new operator.

2 System response after application

  • Stack: As long as the remaining space of the stack is greater than the requested space , the system will provide memory for the program , otherwise an exception will be reported indicating stack overflow.
  • Heap: The operating system has a linked list that records the memory address of the space . When the system receives an application from a program, it will traverse the linked list to find the first heap node whose space is larger than the requested space, and then delete the node from the linked list of free memory nodes. And allocate the space of this node to the program .

Summarize:

(1) heap is a heap, and stack is a stack;

(2) The stack space is automatically allocated/released by the operating system, and the space on the heap is manually allocated/released;

(3) The stack space is limited, and the heap is a large free memory area;

(4) The memory space allocated by the malloc function in C is on the heap, and the corresponding new operator in C++.When the program is compiled, memory allocation for variables and functions is performed on the stack, and parameters are passed on the stack when the function is called during memory operation.

堆和栈的概念存在于数据结构中和操作系统内存中。

在数据结构中,栈中数据的存取方式为先进后出。而堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。完全二叉树是堆的一种实现方式。

在操作系统中,内存被分为栈区和堆区。

栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

堆区内存一般由程序员分配释放,若程序员不释放,程序结束时可能由垃圾回收机制回收。
复制代码

How to upload files

​ Use the getData method to obtain cutting parameters based on server-side cutting

​ console.log(this.cropper.getData())

​ Pure client-side cropping uses getCroppedCanvas to get the cropped file object

  • First look at the interface document

  • 看请求头:
    如果接口要求 Content-Type 是 application/json
    则传递普通 JavaScript 对象
    axios会自动转为json对象
    
    如果接口要求 Content-Type 是 multipart/form-data
    则你必须传递 FormData 对象
    
    const formData = new FormData()
            formData.append('photo', blob)
    
    // 点击完成时间
    onConfirm () {
    
    
      // 基于服务端的裁切使用 getData 方法获取裁切参数
      // console.log(this.cropper.getData())

      // 纯客户端的裁切使用 getCroppedCanvas 获取裁切的文件对象
      this.cropper.getCroppedCanvas().toBlob(async blob => {
    
    
        // console.log(blob) // 裁剪后的结果信息
        // 弹出loading页面
        this.$toast.loading({
    
    
          message: '保存中...',
          forbidClick: true, // 禁止背景点击
          duration: 0 // 持续展示
        })
        try {
    
    
          // 1.创建formData对象
          const obj = new FormData()
          // 2.给对象obj添加key和value
          obj.append('photo', blob)
          // 3.发请求
          const {
    
     data } = await updateUserPhoto(obj)
          // 4.更新父组件对象
          this.$emit('update:photo', data.data.photo)
          // 5.关闭弹层
          this.$emit('update:close', false)
          this.$toast.success('修改成功')
        } catch (error) {
    
    
          this.$toast.fail('修改失败')
        }
      })
    }

What is BFC

The Block Formatting Context (BFC) is part of the visual CSS rendering of a web page, and is the area where the layout process for block-level boxes occurs, and where floating elements interact with other elements.

The following methods create a block formatting context:

  • root element ( <html>)
  • floating element ( floatvalue is not none)
  • Absolutely positioned elements ( positionvalues ​​are absoluteor fixed)
  • inline-block element ( displayvalue inline-block)
  • table_cell ( displayvalue table-cell, default for HTML table cells)
  • table_title ( displayvalue table-caption, HTML table_title default)
  • Anonymous table cell element ( displayvalues ​​are table, table-row, table-row-group, table-header-group, table-footer-group(default for HTML table, tr, tbody, thead, tfoot respectively) or inline-table)
  • overflowA block element with a value other visiblethanclip
  • displayflow-rootelements with value
  • containan element with a value of layout, orcontentpaint
  • flex elements ( displayvalues ​​are direct children of flexor inline-flexelements), if they are neither flex , grid nor table containers themselves
  • Grid elements ( displayvalues grid​​are inline-griddirect children of the or element), if they are neither flex , grid , nor table containers themselves
  • multi-column container ( column-countor column-width(en-US) value not for auto, including column-countfor 1)
  • column-spanElements with a value allof always create a new BFC, even if the element is not wrapped in a multi-column container ( spec change , Chrome bug )

Formatting context affects layout, usually, wewill create new BFCs for positioning and clearing floats, instead of changing the layout, because it will:

  • contains inner float
  • exclude external floats
  • prevents margins from overlapping (the block's margin-top and margin-bottom are sometimes merged (collapsed) into a single margin whose size is the maximum value of the single margin (or if they are equal, only one of them), this behavior is called margin collapse . )

There are three situations in which margins overlap:

  1. The margins between two adjacent elements overlap unless the latter element is cleared with clear-fix .
  2. Without content to separate the parent and descendant elements, the outer boundaries of the parent block element and its descendant block elements will overlap, and the overlap will eventually overflow outside the parent block element.
  3. Empty block-level elements : Border collapse also occurs when the top border of a block element margin-topis glued directly to the bottom border of the element .margin-bottomThis happens when a block element has no border set at allborder, padding padding, height height, minimum height min-height, maximum height max-height, when the content is set to inline or when clear-fix is ​​added.

==Note:== Elements with float floating and position=absolute absolute positioning will not produce margin overlapping behavior.

What are the ways of js lazy loading?

The loading, parsing, and execution of js will block the rendering process of the page, so we hope that the js script can be loaded as lazy as possible to improve the rendering speed of the page. A few ways I've learned are:

The first method is that we generally use theput the js script at the bottom of the document, to make the js script load and execute at the end as much as possible.

The second way is to add to the js scriptdefer attribute, this attribute will allow the script to be loaded and parsed synchronously, and then the script file will be executed after the document is parsed, so that the rendering of the page will not be blocked. Multiple scripts with the defer attribute set end up executing sequentially by specification , but this may not be the case in some browsers.

The third way is to add to the js scriptasync attribute, this attribute will make the script load asynchronously , and will not block the parsing process of the page, but execute the js script immediately after the script is loaded. At this time, if the document is not parsed, it will also be blocked. The execution order of scripts with multiple async attributes is unpredictable, and generally will not be executed sequentially in the order of the code .

The fourth way isCreate DOM tags dynamicallyIn this way, we can monitor the loading event of the document , and then dynamically create script tags to import js scripts when the document is loaded.

What is Ajax? How to create one?

My understanding of ajax is that it is a method of asynchronous communication, by directly initiating http communication from the js script to the server, and then updating the corresponding part of the webpage according to the data returned by the server without refreshing the entire page. There are several steps to create an ajax:

The first is to create an XMLHttpRequest object.

Then use the open method on this object to create an http request. The parameters required by the open method are the method of the request, the address of the request, whether it is asynchronous, and the user's authentication information . Before making a request, we can add some information and listener functions to this object. For example, we can add header information to the request through the setRequestHeader method. We can also add a status listener function to this object. An XMLHttpRequest object has a total of 5 states . When its state changes, the onreadystatechange event will be triggered. We can set the listener function to process the result of the successful request. When the readyState of the object changes to 4, it means that the data returned by the server has been received. At this time, we can judge the status of the request. If the status is 2xx or 304, it means the return is normal. At this time, we can update the page through the data in the response. When the object's properties and listener functions are set

Finally, we call the sent method to initiate a request to the server, and parameters can be passed in as the sent data body.xhr.send(null);

let xhr = new XMLHttpRequest();

// 创建 Http 请求
xhr.open("GET", SERVER_URL, true);

// 设置状态监听函数
xhr.onreadystatechange = function() {
     
     
  if (this.readyState !== 4) return;

  // 当请求成功时
  if (this.status === 200) {
     
     
    handle(this.response);
  } else {
     
     
    console.error(this.statusText);
  }
};

// 设置请求失败时的监听函数
xhr.onerror = function() {
     
     
  console.error(this.statusText);
};

// 设置请求头信息
xhr.responseType = "json";
xhr.setRequestHeader("Accept", "application/json");

// 发送 Http 请求
xhr.send(null);

What is anti-shake and throttling?

introduce

In JavaScript, anti-shake and throttling are actually a very important concept. The main application scenarios are events that will be triggered frequently, such as monitoring scrolling and liking functions. It is impossible to send data to the background once you like it. At this time, anti-shake and throttling are required.

The core of anti-shake and throttling is the timer. We need to know a concept of the timer, which is to clear the timer after timing and before it is triggered. This timer method will not be triggered.

The function of the anti-shake function is to control the execution times of the function within a certain period of time. Anti-bounce means that the function will only be executed once (the last time) within N seconds, and if it is triggered again within N seconds, the delay time will be recalculated.

The role of the throttling function is to specify a unit time, and the function execution can only be triggered once at most within this unit time. If the function is triggered multiple times within this unit time, only one time will take effect.

In vue we can use lodashone of _debounce

Note that the first parameter is the function, and the second parameter is the delay time

pre-parsing

1. Our js engine runs js in two steps: pre-parsing code execution

​ (1). The pre-parsing js engine will promote all var and functionto the front of the current scope

​ (2). Code execution is executed from top to bottom in the order in which the code is written

2. Pre-parsing is divided into variable pre-parsing (variable promotion) and function pre-parsing (function promotion)

(1) Variable promotion is to promote all variable declarations to the front of the current scope without promoting assignment operations

(2) Function promotion is to promote all function declarations to the front of the current scope without calling the function

  • Notice
    • Global variables cannot access local variables
    • Adding the var keyword inside the function is local, and the formal parameters are also local (variable assignment without adding var inside is also a global variable)
    • If there is no var keyword or no parameters are passed, a=1 is global

prototype chain

  • As long as __proto__the prototype points to the prototype object, but Object.prototype.__proto__ it points to an empty (null)

​ Each instance object has a __proto__ attribute, which points to the prototype object of the constructor. The prototype object of the constructor is also an object, and also has the __proto__ attribute, so that it is formed layer by layer.prototype chain

Constructor instance and prototype object triangle

1. The prototype attribute of the constructor points to the prototype object of the constructor
2. The instance object is created by the constructor, and the __proto__ attribute of the instance object points to the prototype object of the constructor
3. The constructor attribute of the prototype object of the constructor points to Constructor, the constructor attribute of the prototype of the instance object also points to the constructor

Prototype Chain and Member Lookup Mechanism

__proto__The significance of the object prototype is to provide a direction, or a route, for the object member search mechanism.

Any object has a prototype object, that is, the prototype attribute. Any prototype object is also an object, and the object has the __proto__ attribute. In this way, looking up layer by layer, a chain is formed, which we call the prototype chain;

当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。
如果还没有就查找原型对象的原型(Object的原型对象)。
依此类推一直找到 Object 为止(null)。


查找原则:
	实例对象访问属性:
		先去本身构造函数上去查找,如果本身没有要查找的属性或者方法,会自动去原型对象去查找
		如果原型对象也没有,再去原型对象的原型对象去查找。
		如果都没有返回undefined。 如果找到了停止查找
设置原则:
	给实例对象设置一个属性,本质上是给实例添加属性,并不会修改原型的内容。

Guess you like

Origin blog.csdn.net/qq_43375584/article/details/125565184