This article is collected on GitHub DailyQuestion: DailyQuestion, including big factory promotion opportunity, interview book and several interview questions, study 5 minutes a day, a year to enter the big factory.

  • Dachang Face Sutra
  • Big push

01 What are anti-shake and throttling, and what are their application scenarios

Communicate and discuss in the Issue: 01 What are anti-shake and throttling, and what are their application scenarios

Image stabilization (debounce)

Anti-shake, as the name implies, to prevent jitter, so as not to mistake an event for many times, typing the keyboard is a daily contact with anti-shake operation.

To understand a concept, you must first understand the scenario in which the concept is applied. In the JS world, what is the scene of anti – shake

  1. To prevent users from clicking buttons such as login and SMS so fast that multiple requests are sent, you need to avoid shaking
  2. When adjusting the browser window size, the number of resize times is too frequent, resulting in too much calculation. At this time, it needs to be in place once, so it uses anti-shake
  3. The text editor saves in real time and saves after one second when there is no change operation

ClearTimeout (timer)

function debounce (f, wait) {
  let timer
  return (. args) = > {
    clearTimeout(timer)
    timer = setTimeout((a)= >{ f(... args) }, wait) } }Copy the code

The throttle (throttle)

Throttling, as the name suggests, controls the flow of water. Control the frequency of events, such as 1 second, or even 1 minute. This parameter is similar to the Rate Limit controlled by the server and gateway.

  1. scrollEvent, calculate position information every second, etc
  2. Browser plays events, calculates progress information every second, and so on
  3. Input box Search and send requests in real time display dropdown list, send requests every second (also can be made to shake)

Timer =timeout

function throttle (f, wait) {
  let timer
  return (. args) = > {
    if (timer) { return }
    timer = setTimeout((a)= >{ f(... args) timer =null
    }, wait)
  }
}
Copy the code

Summary (Brief answer)

  • Anti – shake: Prevents jitter. The event trigger can be reset within a unit time, preventing the event from being triggered multiple times by accidental injury. The code implementation focuses on clearing clearTimeout. Anti-shaking can be compared to waiting for an elevator. As soon as one person comes in, you have to wait a little longer. Service scenarios avoid repeated submission when the login button is clicked multiple times.
  • Throttling: Controls traffic. Events can be triggered only once per unit of time, similar to the Rate Limit on the server. Timer =timeout; The timer = null. Throttling can be likened to going through a traffic light, waiting for each red light to pass one batch.

02 In front-end development, how to obtain the unique identity of the browser

More description: How do I get a unique browser identity, and how does that work

How do I get the unique identity of the browser in front end development

Because different system graphics cards have different rendering parameters and anti-aliasing algorithms when drawing canvas, the CRC check of the drawn picture data is also different.

function getCanvasFp () {
  const canvas = document.getElementById('canvas')
  const ctx = canvas.getContext('2d')
  ctx.font = '14px Arial'
  ctx.fillStyle = '#ccc'
  ctx.fillText('hello, shanyue'.2.2)
  return canvas.toDataURL('image/jpeg')}Copy the code

Therefore, browser fingerprint information can be obtained according to Canvas.

  1. drawcanvasTo obtainbase64The dataurl
  2. For the string dataURLmd5Fingerprint information is obtained by calculation

But there are mature solutions for common requirements, and the following libraries can be used in a production environment

  • fingerprintjs2

It gets the browser fingerprint information based on the following information, which is called component

  1. canvas
  2. webgl
  3. UserAgent
  4. AudioContext
  5. Support for new apis, etc
requestIdleCallback(function () {
  Fingerprint2.get((components) = > {
    const values = components.map((component) = > component.value)
    const fp = Fingerprint2.x64hash128(values.join(' '), 31)})})Copy the code

In Fingerprintjs2, there are also categories for Components

  • browser independent component: somecomponentThe same device can get the same value across browsers, and some individual browsers can get different values
  • stable component: somecomponentThe value changes after the refresh and is called an unstable component

In actual services, you can select appropriate components based on services

const options = {
  excludes: {userAgent: true.language: true}}Copy the code

Short answer

The browser fingerprint information can be obtained according to Canvas

  1. drawcanvasTo obtainbase64The dataurl
  2. For the string dataURLmd5Fingerprint information is obtained by calculation

For use in a production environment, you can use Fingerprintjs2 to select the appropriate component based on business requirements, such as whether a single device is cross-browser

03 How do I Obtain the Client IP Address in a Server Application

How do I get a client IP address in a server application

If you havex-forwarded-forRemoteAddr; otherwise remoteAddr of the socket to which the connection was established.

This header is forwarded-for. The format of this header is as follows. The first IP address of this header is forwarded-for

X-Forwarded-For: 203.0113.195..70.413.18..150.172238.178.
X-Forwarded-For: <client>, <proxy1>, <proxy2>
Copy the code

Here’s how KOA gets the IP

  get ips() {
    const proxy = this.app.proxy;
    const val = this.get(this.app.proxyIpHeader);
    let ips = proxy && val
      ? val.split(/\s*,\s*/)
      : [];
    if (this.app.maxIpsCount > 0) {
      ips = ips.slice(-this.app.maxIpsCount);
    }
    return ips;
  },

  get ip() {
    if (!this[IP]) {
      this[IP] = this.ips[0] | |this.socket.remoteAddress || ' ';
    }
    return this[IP];
  },
Copy the code

See source code: github.com/koajs/koa/b…

04 How do JS replace all one substring with another

Suppose you have A string ‘hello.hello.hello.’ that needs to be replaced with ‘AAA’, i.e. ‘A’

Exchange and discuss in Issue: how does 04 JS replace all one substring with another

If you want to replace a String in full, you can use string.prototype. replace(re, replacer), where global Flag is enabled for regular expressions

const s = 'foo foo foo'
s.replce(/foo/g.'bar')
Copy the code

Can regular expressions be used instead of substrings

A: No, because when using substrings to build a re, there may be special characters, which may cause problems, as shown below

// Expect result: 'AhelloX hello3 '
> 'hello. helloX hello3 '.replace(new RegExp('hello. '.'g'), 'A')
< "AAA"
Copy the code

Replacing substrings in javascript can only be done in one clever way: str.split(‘foo’).join(‘bar’)

> 'hello. hello. hello. '.split('hello. ').join('A')
< "AAA"
Copy the code

Is really a clever (stupid) wonderful (clumsy) method !!!!! Perhaps TC39 also realized a problem, and a new API was created in ESNext

String.prototype.replaceAll()

'aabbcc'.replaceAll('b'.'. '); 
// 'aa.. cc'
Copy the code

Detailed documentation in the String. The prototype. ReplaceAll

Summary (and direct answers)

Two ways

  • str.split('foo').join('bar')
  • str.replaceAll('foo', 'bar')In theESNextMedium, the current support is not good

05 How do I Obtain and Monitor the memory of a process

More description: when writing scripts, sometimes there will be too much memory, so how do we know the memory of a process? And how is it monitored

How do I get and monitor the memory of a process

Ps lets you know how much memory a process occupies

$ ps -O rss -p 3506
  PID   RSS S TTY          TIME COMMAND
 3506  6984 S pts/1    00:00:00 vim
Copy the code

If you want to monitor memory, be sure to use the process-all-purpose pidstat command (PS: the name sounds obvious)

## -r Displays memory information
## -p Specifies the PID
## 1: Print once every second$pidstat -r -p 3506 1 Linux 3.10.0-957.21.3.el7.x86_64 (shanyue) 11/04/19_x86_64_ (2 CPU) 20:47:35 UID PID minflt/s Majflt /s VSZ RSS %MEM Command 20:47:360 0 3506 0.00 0.00 139940 6984 0.18 vim 20:47:370 0 3506 0.00 0.00 139940 6984 0.18 Vim 20:47:350 0.00 0.00 139940 6984 0.18 vim 20:47:350 0.00 0.00 0.00 139940 6984 0.18 vim 20:47:41 0 3506 0.00 0.00 139940 6984 0.18 vimCopy the code

Pidstat is a Linux performance tool under SYSstat, but how do you locate memory changes on the MAC? You can use the all-purpose top/ hTOP

$ htop -p 31796
Copy the code

conclusion

In short, there are three commands

  1. pidstat -r
  2. htop/top -p
  3. ps -O rss -p

For more information about monitoring metrics, see my article: Linux Monitoring Metrics Notes

06 What if CORS needs to specify multiple domain names

06 CORS What if you need to specify multiple domain names

CORS controls which domain names can share resources by controlling access-control-allow-origin. The value can be

Access-Control-Allow-Origin: <origin> | *
Copy the code

* indicates all domain names and origin indicates a specific domain name.

Access-control-allow-origin = access-Control-allow-Origin = access-Control-allow-Origin = access-Control-allow-Origin

Request header: Origin

Not all requests are automatically tagged with Origin, and the logic for putting Origin in a browser is as follows

  1. If there is cross-domain, bringOriginThe value is the current domain name
  2. If no cross-domain exists, noOrigin

Access-control-allow-origin = access-Control-allow-origin = access-Control-allow-origin = access-Control-allow-origin

  1. If the request header does not carryOrigin, if no cross-domain is proved, no processing is done
  2. If the request header containsOrigin, prove cross-domain, according toOriginSet the correspondingAccess-Control-Allow-Origin: <Origin>

Using pseudocode, the implementation is as follows:

// Get the Origin header
const requestOrigin = ctx.get('Origin');

// If not, skip it
if(! requestOrigin) {return await next();
}

// Set the response header
ctx.set('Access-Control-Allow-Origin', requestOrigin)
Copy the code

Vary: Origin

At this point, multiple domains can control the CORS, but it is assumed that two domains access the cross-domain resources of static.shanyue.tech

  1. foo.shanyue.techIs returned in the response headerAccess-Control-Allow-Origin: foo.shanyue.tech
  2. bar.shanyue.techIs returned in the response headerAccess-Control-Allow-Origin: bar.shanyue.tech

Everything looks fine, but what if there’s a cache in the middle?

  1. foo.shanyue.techIs returned in the response headerAccess-Control-Allow-Origin: foo.shanyue.techIs cached by CDN
  2. bar.shanyue.tech, returned in the response header due to the cacheAccess-Control-Allow-Origin: foo.shanyue.techA cross-domain problem occurs

At this point, Vary: Origin comes into play, representing caching different resources for different Origin

Summary (Brief answer)

How does CORS specify multiple domain names?

Set the access-Control-allow-Origin response header based on the Origin in the request header

  1. Always setVary: OriginTo avoid CDN cache damage to CORS configuration
  2. If the request header does not carryOrigin, if no cross-domain is proved, no processing is done
  3. If the request header containsOrigin, proving browser access across domains, according toOriginSet the correspondingAccess-Control-Allow-Origin: <Origin>

Using pseudocode, the implementation is as follows

// Get the Origin header
const requestOrigin = ctx.get('Origin');

ctx.set('Vary'.'Origin')

// If not, skip it
if(! requestOrigin) {return await next();
}

// Set the response header
ctx.set('Access-Control-Allow-Origin', requestOrigin)
Copy the code

Related questions: How to avoid CDN caching mobile pages for PC

07 Since the CORS configuration can do cross-domain control, can it prevent CSRF attacks

07 Since cORS configuration can do cross-domain control, can it prevent CSRF attacks

It doesn’t help CORS at all

  1. Form submissions do not pass CORS detection. You can test them locally
  2. Even throughxhrfetchCommit is blocked by CORS,But for simple requests, the request is still sent, has caused an attack

08 How do I Avoid CDN Caching Mobile Pages for the PC

08 How to avoid CDN caching mobile pages for PC

This problem does not occur if PC and mobile are the same code. This problem occurs when PC and mobile are two sets of code, but share the same domain name.

Use nginx configuration as follows, according to UA to determine whether mobile terminal, and follow different logic (determine whether mobile terminal is prone to problems)

Location / {// default PC root /usr/local/website/web; # UA, access to the mobile end if ($http_user_agent ~ * "(Android | webOS | the | the | BlackBerry)") {root/usr/local/website/mobile; } index index.html index.htm; }Copy the code

Solutions typically use the Vary response header to control the CDN’s caching of different request headers.

Here you can useVary: User-Agent, indicating that if the User-Agent is different, the request is re-initiated instead of reading the page from the cache

Vary: User-Agent
Copy the code

Of course, if there are too many user-agents, there will be too many cache invalidation.

Short answer

Vary: user-Agent is used to cache by UA.

Vary: User-Agent
Copy the code

However, it is best not to do this. If there are two sets of codes for PC and mobile, it is recommended to use two domain names for the following reasons

  1. nginxDetermine whether the mobile terminal is prone to error
  2. Not cache friendly

09 How to implement single and double row fringe style of table

09 How to implement single and double row stripe style in the table

Through cSS3 pseudo-class :nth-child to achieve. Nth-child (an+b) matches subscript {an+b; n = 0, 1, 2, … } and the result is a child of an integer

  • nth-child(2n)/nth-child(even): Double line style
  • nth-child(2n+1)/nth-child(odd): Single-line style

Where tr represents rows in the table, it is easy to implement a single or double row style in the table:

tr:nth-child(2n) {
  background-color: red;
}


tr:nth-child(2n+1) {
  background-color: blue;
}
Copy the code

In the same way:

  1. How to match the first three child elements::nth-child(-n+3)
  2. How to match the last three child elements::nth-last-child(-n+3)

10 Brief CSS Specificity

Communicate and discuss in Issue: 10 CSS Specificity

CSS Specificity refers to the weight of a CSS selector. The following three types of selectors decrease in sequence

  1. idSelectors, such as#app
  2. class,attributepseudo-classesSelectors, such as.header,[type="radio"]:hover
  3. typeTag selectors and pseudo-element selectors, such ash1,p::before

Where wildcard selector *, combinatorial selector + ~ >, negative pseudo-class selector :not() has no effect on priority

Codepen :not has no effect on the priority of the selector

Module. exports: exports

What is the difference between module. Exports and exports in 11 nodes

In a word:exportsmodule.exportsIfexportsWithout reassignment, there is no difference

Similar to the following

const exports = module.exports
Copy the code

How can the following result be derived?

module.exports = 100
exports = 3
Copy the code

Exports obviously export 100, after all exports are reassigned.

How does that work in the Node source code? The essence of exports can be seen from the source code

See source: github.com/nodejs/node… , you can see that it fits the conjecture

As you know, all module code in Node is wrapped in this function

(function(exports, require, module, __filename, __dirname) {
  exports.a = 3
});
Copy the code

Where did exports come from

const dirname = path.dirname(filename);
const require = makeRequireFunction(this, redirects);
let result;
// The essence of exports can be seen here
const exports = this.exports;
const thisValue = exports;
const module = this;
if (requireDepth === 0) statCache = new Map(a);if (inspectorWrapper) {
  result = inspectorWrapper(compiledWrapper, thisValue, exports,
                            require.module, filename, dirname);
} else {

  // here is the module wrapper function
  result = compiledWrapper.call(thisValue, exports, require.module,
                                filename, dirname);
}
Copy the code

12 How to Obtain the Number of Online Users (Concurrent Users) in the Current System?

More description: Some SaaS systems will limit the number of team members and the number of concurrent online users based on Pricing considerations. How to achieve this

12 How to obtain the number of online users (concurrent users) in the current system

Some SaaS systems limit the number of team members and the number of concurrent online users based on pricing strategies. How to achieve this?

The number of concurrent users can be realized by redis zset.

When a user requests any interface, a Middleware implementation handles the following logic

// When a user accesses any interface, write zset to that user Id
await redis.zadd(`Organization:${organizationId}:concurrent`.Date.now(), `User:${userId}`)

// Query the number of concurrent requests in the current organization
Check the number of concurrent requests by querying active users within a minute, and throw a specific exception if the number exceeds that
const activeUsers = await redis.zrangebyscore(`Organization:${organizationId}:concurrent`.Date.now() - 1000 * 60.Date.now())

// Check the number of concurrent requests
const count = activeUsers.length

// Delete expired users
await redis.zrembyscore(`Organization:${organizationId}:concurrent`.Date.now() - 1000 * 60.Date.now())
Copy the code

conclusion

  1. Each time a user accesses the service, the user’s ID is written to the priority queue with the weight being the current time
  2. Calculate the number of users of the organization within a minute based on the weight (i.e., time)
  3. Delete users that have expired for more than a minute

13 How to convert JSON data to Demo. json and download the file

13 how to convert JSON data to demo.json and download the file

Json is treated as a string and can be downloaded using the DataURL

Text -> DataURL

In addition to using the DataURL, you can also convert it to an Object URL for downloading

Text -> Blob -> Object URL

You can paste the following code directly into the console download file

function download (url, name) {
  const a = document.createElement('a')
  a.download = name
  a.rel = 'noopener'
  a.href = url
  // Trigger the mock click
  a.dispatchEvent(new MouseEvent('click'))
  / / or a.c lick ()
}

const json = {
  a: 3.b: 4.c: 5
}
const str = JSON.stringify(json, null.2)

DataURL -> DataURL
const dataUrl = `data:,${str}`
download(dataUrl, 'demo.json')

// Text -> Blob -> ObjectURL
const url = URL.createObjectURL(new Blob(str.split(' ')))
download(url, 'demo1.json')
Copy the code

conclusion

  1. Simulation download, you can create a new one<a href="url" download><a>Tag and seturldownloadProperties to download
  2. You can do this by puttingjsonintodataurlTo construct the URL
  3. You can do this by puttingjsonconvertBlobAgain intoObjectURLTo construct the URL

14 How do I listen to clipboard content in the browser

14 How do I listen to clipboard content in the browser

The Clipboard API allows you to access Clipboard contents, but you need to obtain clipboard-read permission. Here is the code for reading Clipboard contents:

// Can read the clipboard permission
// result.state == "granted" || result.state == "prompt"
const result = await navigator.permissions.query({ name: "clipboard-read" })

// Get the clipboard contents
const text = await navigator.clipboard.readText()
Copy the code

Note: This method does not take effect in DevTools

Related questions: [Q019] How to implement the function of selected copy

Pay attention to my

My name is Shanyue and I am dedicated to answering one of the most frequently asked interview questions in five minutes each day.

Welcome to pay attention to the public account [Internet Big factory recruitment], regularly push big factory internal promotion information and brief answers to interview questions, learn five minutes a day, half a year into the big factory