Front end interview questions (JS) suggestions collection, constantly updating

Keywords: Javascript Front-end html5 html

Please use js to implement a stopwatch timer program

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>timer</title>
</head>

<body>
    <div id="counter"></div>
</body>

</html>
<script>
    /* Select the desired couter */
    const ele = document.getElementById('counter');
    /* Define two variables  */
    let intervalId, seconds;
    /* Define a method for calculating time */
    function counter() {
        /* Define timer  */
        intervalId = window.setInterval(() => {
            --seconds;
            ele.innerText = seconds;
            if (seconds === 0) {
                alert('Timing end');
                window.clearInterval(intervalId);
            }
        }, 1000);
    }

    function stopCounter() {
        window.clearInterval(intervalId);
    }

    function resumeCounter() {
        counter();
    }

    seconds = 100;
    counter();
</script>

  Operation results

How to implement the expiration time function when simulating localStorage

1.Record the effective deadline when storing
2.Judge whether the valid time is exceeded when fetching data,Within the validity period, return,If not, prompt or return null and delete it
class MyStorage {
  get(key) {
    const wrapValue = localStorage.getItem(key)
    if (wrapValue == null) {
      return undefined
    }
    
    const {value, expires} = JSON.parse(wrapValue)
-    if ((expires != null && Date.now() < expires) || expires == null) {
+    if (!expires || Date.now() < expires) {
      return value
    } 
-
+   localStorage.rmeoveItem(key)
    return undefined
  }

  set(key, value, period) {
    const wrapValue = { value };
    if (period != null) {
      wrapValue.expires = Date.now() + period;
    }

    localStorage.setItem(key, JSON.stringify(wrapValue));
  }
}

Please use js to realize the free combination of goods, and talk about your ideas

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>commodity sku</title>
</head>

<body>

</body>

</html>
<script>
    var a = ['yellow', 'green']
    var b = ['s', 'l']
    var c = ['large', 'Small']

    function decar(...args) {
        return args.reduce((acc, item) => {
            const res = []
            for (let i = 0; i < acc.length; i++) {
                for (let j = 0; j < item.length; j++) {
                    const prev = [].concat(acc[i])
                    res.push([...prev, item[j]])
                }
            }
            return res
        })
    }
    decar(a, b, c)
    console.log(decar(a, b, c))
</script>

Operation results

js: what is the difference between undefined and ReferenceError: xxx is not defined?

undefined Yes, the variable is declared but not assigned
ReferenceError: xxx is not defined yes xxx Undeclared, non-existent variable used

JavaScript Number.toPrecision() Function explanation
JavaScript:

numberObject.toPrecision( [ precision ] )

If not provided precision Parameter or its value is undefined,Will be called instead toString()Method.
If a parameter is provided, the parameter precision Must be between [1, 21] Otherwise, an error will be reported.
If the number of significant digits is greater than precision,Will be based on paragraph precision + 1 Significant digits are rounded.
Return value

toPrecision()The return value of the function is String Type that returns the representation of the number in exponential counting or fixed-point notation. If the number of significant digits is less than precision The decimal part is filled with 0 of the corresponding digit.

If parameter precision If it is greater than or equal to the number of digits in the integer part of the number, the return value will adopt the fixed-point representation; Otherwise, the exponential counting method will be used.

The number of significant digits is the first non-zero number from the number(Including integer part and decimal part)Number of digits to start calculation. 


Ex amp le & Description

JavaScript:

//toPrecision() will be rounded

var num = 423.536;
// The toString() method is called
document.writeln( num.toPrecision() ); // 423.536

num = 562345.12456;
// Since the integer part has 6 digits, it is required to have only 3 significant digits, which must be expressed by exponential counting method.
document.writeln( num.toPrecision( 3 ) ); // 5.62e+5

num = -2651.10;
// The integer part has 4 bits, and the required significant number is 4 bits, which adopts fixed-point representation
document.writeln( num.toPrecision( 4 ) ); // -2651

num = 4564561.12457;
// The integer part has 7 bits, and the significant number is required to be 1 bit. The exponential counting method is adopted
document.writeln( num.toPrecision( 1 ) ); // 5e+6

num = 231;
// The integer part has 3 digits, and the significant number is required to be 5 digits. The fixed-point representation is adopted, and two zeros are filled in the decimal part
document.writeln( num.toPrecision( 5 ) ); // 231.00



 

Get the compatible writing method of the scroll bar height of the current page of the browser

document.documentElement.scrollTop || document.body.scrollTop;

What is Number.call.call(Number, undefined, 0) equal to?

call The first parameter of is used to change the context, because it is not used this,First parameter Number It's actually useless.

    Number.call(Number, undefined, 0) Equivalent to Number(undefined, 0),because Number Only the first parameter is accepted.
    Number.call.call(Number, undefined, 0) Equivalent to Number.call(undefined, 0),that is Number(0). 

What is the difference between ReferenceError and TypeError?

ReferenceError

It refers to a reference error, such as trying to access an undefined variable or accessing a variable without promotion in advance, which will cause this error:

console.log(foo);  // ReferenceError: foo is not defined
let foo = 1;

TypeError

Refers to a type error.

As we all know, JavaScript is a weakly typed language, which is not only its advantage, but also often criticized. You never know whether a + b is doing numerical addition and subtraction or string splicing, and it seems that a + b almost never reports an error.

tc39 has almost quadrupled the frequency of TypeError since ES5 to ES6. The purpose is to standardize and emphasize the concept of type and avoid the semantic uncertainty of JavaScript caused by too vague concept of type.
 

Symbol() + 1; // TypeError: Cannot convert a Symbol value to a number

({ toString: () =>({}) }) + 'a';  // TypeError: Cannot convert object to primitive value

This makes JavaScript more standardized. When a method parameter needs a number but receives an object, instead of asking it to return NaN, throw TypeError continuously.

How to avoid JS Precision of floating point operation (example: 0).1+0.7=0.7999999999999999)
 function precision(num1,num2){
        num1Length = num1.toString().length;
        num2Length = num2.toString().length;
        let len =  num1Length > num2Length ? num1Length : num2Length;
        return (num1 + num2).toPrecision(len);
    }
    console.log(precision(0.1,0.7));

Detailed explanation of JavaScript Number.toPrecision() function

JavaScript:

numberObject.toPrecision( [ precision ] )

If the precision parameter is not provided or its value is undefined, the toString() method is called instead for processing.
If a parameter is provided, the parameter precision must be between [1, 21], otherwise an error will be reported.
If the number of significant digits is greater than precision, it will be rounded according to the significant digit of precision + 1.
Return value

The return value of the toPrecision() function is of type String, which returns the number in the form of exponential counting or fixed-point representation. If the significant digits of the number are less than the precision digits, the decimal part is filled with 0 of the corresponding digits.

If the parameter precision is greater than or equal to the number of digits of the integer part of the number, the return value will adopt the fixed-point representation; otherwise, the exponential counting method will be adopted.
 

The number of significant digits is the first non-zero number from the number(Including integer part and decimal part)Number of digits to start calculation. 

Ex amp le & Description
 

JavaScript:

//toPrecision() will be rounded

var num = 423.536;
// The toString() method is called
document.writeln( num.toPrecision() ); // 423.536

num = 562345.12456;
// Since the integer part has 6 digits, it is required to have only 3 significant digits, which must be expressed by exponential counting method.
document.writeln( num.toPrecision( 3 ) ); // 5.62e+5

num = -2651.10;
// The integer part has 4 bits, and the required significant number is 4 bits, which adopts fixed-point representation
document.writeln( num.toPrecision( 4 ) ); // -2651

num = 4564561.12457;
// The integer part has 7 bits, and the significant number is required to be 1 bit. The exponential counting method is adopted
document.writeln( num.toPrecision( 1 ) ); // 5e+6

num = 231;
// The integer part has 3 digits, and the significant number is required to be 5 digits. The fixed-point representation is adopted, and two zeros are filled in the decimal part
document.writeln( num.toPrecision( 5 ) ); // 231.00

For example, what are the writing methods of js immediate execution function?

1,(function(){
//code
}())

2,!function(){
//code
}()

3,!(function(){
//code
})()

4,!(()=>{
//code
})()

What is the difference between for in and for of?  

for of For traversing arrays and iteratable objects, the result is entity({key: value}), for in The property name of the object is obtained by traversing the object
for in Cannot be used to traverse an array, for in Will put the length And other unnecessary attributes are traversed together
for of It cannot be used to traverse the object. The object is a non iteratable object.

Write a method to determine whether all the elements in the array are the same

const isSameArray = function (array) {
  if (Array.isArray(array)) {
    return new Set(array).size === 1;
  }

  return false;
};

What are the ways to prevent duplicate ajax requests? What are the advantages and disadvantages of each?  

// Method 1 anti shake

function debounce(f, ms) {
let time;
return function(){
let arg = Array.prototype.slice.call(arguments, 1);
if(time) {
clearTimeout(time);
}
time = setTimeout(function(){
f.apply(this, arg)
},ms)
}
}

// Method 2 throttling
function throttle(f, ms){
let lastTime = 0;
return function(){
let arg = Array.prototype.slice.call(arguments, 1);
let newTime = Date.now();
if(newTime-lastTime > ms) {
setTimeout(function(){
f.apply(this, arg)
},ms)
}
lastTime = newTime;
}
}
    Anti shake method: if the request is repeated for a period of time, the request will be cancelled
    Throttling method: you can only request once in a period of time. The next request must be made after the previous request is completed
    Equivalent method:The incomplete request status is no longer requested, but the same content is returned directly after completion

  Please use js to implement a two-way linked list

start

The linked list structure is a more basic data structure problem that we are often asked in the interview. At first, we used C + + language to learn the data structure. Recently, in the process of doing the front-end interview questions, we didn't meet the need to use js to realize the double linked list. Baidu found a lot of errors in the articles, so we simply wrote it again and listed some error points. Here are some examples Let's take a more detailed step-by-step look at the implementation ideas and steps. Compared with C + + language, the implementation of JS is very simple. There is no need to create cumbersome objects, which is more intuitive and easy to understand;
First, let's take a look at the structure of the two-way linked list:
Insert picture description here
Each node contains three parts, the pointer to the previous node (pre), the pointer to the next node (next), and its own data element, so we can write out the node object first

function Node: defines a node object

function Node(element) {
  this.element = element
  this.next = null
  this.previous = null
}

Then we begin to implement the algorithm of inserting linked list
Insert picture description here

(Declaration) this in the following function is the last instance of initializing the linked list. Don't be confused here. You can pull it to the bottom of our initialization linked list. I'm sure you'll understand

**`function insert`:Insert node**

function insert(newelement, currentelement) {
  var newNode = new Node(newelement)
  var currentNode = this.find(currentelement)
  if (currentNode === 'error') {
    console.log('Cannot insert, the node to insert does not exist')
    return
  }
  if (currentNode.next != null) {
    newNode.next = currentNode.next
    currentNode.next = newNode
    newNode.previous = currentNode
    newNode.next.previous = newNode
  } else {
    currentNode.next = newNode
    newNode.previous = currentNode
  }
}

function find: find the insertion position  

function find(element) {
  var currentNode = this.head
  while (currentNode.element != element) {
  /*If we find the last node and haven't found our insertion point, we will return an error*/
    if (currentNode.next == null) {
      console.log('can not find this node; maybe not have this node')
      return 'error'
    }
    currentNode = currentNode.next
  }
  return currentNode
}

The next step is to remove the implementation of the node. If you understand the implementation of the inserted node, the removal will be very simple. I believe everyone can understand it quickly. Here you can directly post the implementation code;  

function remove:Remove a node

function remove(element) {
  var currentNode = this.find(element)
  if (currentNode === 'error') {
    console.log('The node to be removed does not exist')
    return
  }
  /*First, is it the case of head and tail nodes*/

  if (currentNode.next != null && currentNode.previous != null) {
    currentNode.previous.next = currentNode.next
    currentNode.next.previous = currentNode.previous
    currentNode.next = null
    currentNode.previous = null
  } else if (currentNode.previous == null) {
    /*When it's the head node*/
    this.head = currentNode.next
    currentNode.next.previous = null
    currentNode.next = null
  } else if (currentNode.next == null) {
    /*When it is the tail node */

    currentNode.previous.next = null
    currentNode.previous = null
  }
}

Up to now, we have the basic functions. Let's customize some other functions according to our needs  

function lastNode: Last node found

function lastNode() {
  var head = this.head
  while (head.next != null) {
    head = head.next
  }
  return head     //Here, the head is at the position of the tail node
}
function append:Put the node to be added at the end of the linked list

function append(element) {
  var lastnode = this.lastNode()
  var newNode = new Node(element)
  lastnode.next = newNode
  newNode.previous = lastnode
}
function showlist: Print out all nodes of the linked list

function showlist() {
  var head = this.head
  do {
    console.log(head.element)
    head = head.next
  } while (head != null)
  // You can take a look at the problems in the notes below, and leave it to you to think about it
  // while (head.next != null) {
  //   console.log(head.element)
  //   head = head.next
  // }
}

The next step is to initialize the linked list, which is also the instance represented by all this in the above function

function initlist: initialize the linked list and register all methods in the linked list

function initlist() {
  this.head = new Node('one')
  this.find = find
  this.insert = insert
  this.remove = remove
  this.showlist = showlist
  this.lastNode = lastNode
  this.append = append
}

var list = new initlist()
list.insert('two', 'one')
list.insert('four', 'two')
list.insert('three', 'two')

// console.log(list.head.next)
list.showlist()
list.append('A')
list.append('B')
list.insert('B2', 'B')
list.showlist()
console.log(list.lastNode())
// list.remove('one')
// list.showlist()
console.log(list.find('A').previous)
// console.log(list.find('four').previous)
// console.log(list.head.element)

Here are the results:
Insert picture description here
Source code:  

function Node(element) {
  this.element = element
  this.next = null
  this.previous = null
}
function find(element) {
  var currentNode = this.head
  while (currentNode.element != element) {
    if (currentNode.next == null) {
      console.log('can not find this node; maybe not have this node')
      return 'error'
    }
    currentNode = currentNode.next
  }
  return currentNode
}
function insert(newelement, currentelement) {
  var newNode = new Node(newelement)
  var currentNode = this.find(currentelement)
  if (currentNode === 'error') {
    console.log('Cannot insert, the node to insert does not exist')
    return
  }
  if (currentNode.next != null) {
    newNode.next = currentNode.next
    currentNode.next = newNode
    newNode.previous = currentNode
    newNode.next.previous = newNode
  } else {
    currentNode.next = newNode
    newNode.previous = currentNode
  }
}
function remove(element) {
  var currentNode = this.find(element)
  if (currentNode === 'error') {
    console.log('The node to be removed does not exist')
    return
  }
  /*First, is it the case of head and tail nodes*/

  if (currentNode.next != null && currentNode.previous != null) {
    currentNode.previous.next = currentNode.next
    currentNode.next.previous = currentNode.previous
    currentNode.next = null
    currentNode.previous = null
  } else if (currentNode.previous == null) {
    /*When it's the head node*/
    this.head = currentNode.next
    currentNode.next.previous = null
    currentNode.next = null
  } else if (currentNode.next == null) {
    /*When it is the tail node */

    currentNode.previous.next = null
    currentNode.previous = null
  }
}
function showlist() {
  var head = this.head
  do {
    console.log(head.element)
    head = head.next
  } while (head != null)
  // while (head.next != null) {
  //   console.log(head.element)
  //   head = head.next
  // }
}
function initlist() {
  this.head = new Node('one')
  this.find = find
  this.insert = insert
  this.remove = remove
  this.showlist = showlist
  this.lastNode = lastNode
  this.append = append
}
function append(element) {
  var lastnode = this.lastNode()
  var newNode = new Node(element)
  lastnode.next = newNode
  newNode.previous = lastnode
}
function lastNode() {
  var head = this.head
  while (head.next != null) {
    head = head.next
  }
  return head
}
var list = new initlist()
list.insert('two', 'one')
list.insert('four', 'two')
list.insert('three', 'two')

// console.log(list.head.next)
list.showlist()
list.append('A')
list.append('B')
list.insert('B2', 'B')
list.showlist()
console.log(list.lastNode())
// list.remove('one')
// list.showlist()
console.log(list.find('A').previous)
// console.log(list.find('four').previous)
// console.log(list.head.element)

 END

  Does ajax request address only support http/https? Can it support rtmp: / / and other custom protocols?

ajax Only support http/https agreement,
You can customize http Header to indirectly support custom protocols

Please write a method for deep cloning of objects with the best performance

const deepClone = (obj) => {
  const copy = obj instance Array ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
       copy[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
   }
  }
return copy;
}

Is it really unsafe to use ajax requests? Why?

AJAX Is send HTTP A way of requesting, but the browser adds a homology policy to it.
Therefore, a conclusion can be drawn from this point: AJAX Intrinsically safe and HTTP Same request

  Have you ever used pjax? What is its principle?

pushState + ajax = pjax

  Traverse the tree structure according to the element ID and find all the parent element IDs

var list = [{
"orgId": 1,
"orgName": "Principal's office 1",
"parentId": 0
},{
"orgId": 2,
"orgName": "Principal's office 2",
"parentId": 1,
},{
"orgId": 3,
"orgName": "Principal's office 3",
"parentId": 2,
}];

function findParent(idx){
		list.forEach(item => {
		if (idx === item['orgId']){
						let pid = item['parentId']
						console.log(pid)
						findParent(pid)
		}
	})
}
findParent(3);   //2 1 0

  For example, under what circumstances will Object.defineProperty cause circular reference and stack overflow?

var data = {
    count: 1,
    value: 2
}
Object.defineProperty(data, 'count', {
    enumerable: true,
    configurable: true,
    get: function () {
        console.log('You visited count', this.count); // Reading data.count repeatedly causes an error
        return this.value
    },
    set: function (newVal) {
        console.log('You set up. count');
    }
})
console.log(data.count) // Maximum call stack size exceeded

Write a method. When the number of digits of a given number is less than 8, supplement 0 on the left to supplement 8 digits  

function padNumber(n, targetLen, placeholder) {
  const arr = ("" + n).split("");
  const diff = arr.length - targetLen;
  if (diff < 0) {
    return Array(0 - diff)
      .fill(placeholder, 0, 0 - diff + 1)
      .concat(arr)
      .join("");
  } else {
    return arr.join("");
  }
}
console.log(padNumber(3458, 8, "0")); //'00003458'
console.log(padNumber(90990, 3, "-")); //'90990'

What is the difference between innerHTML and outerHTML?  

<div id="test"><h5>Just like you</h5></div>

document.getElementById("test").innerHTML //< H5 > just likes you < / H5 > document.getelementbyid ("test"). Outhtml / / < div id = "test" > < H5 > just likes you < / H5 > < / div > 

What are the methods of js operating nodes?  

Create node

    createElement() Create an element node
    createTextNode() Create a text node
    createAttribute() Create an attribute node
    createComment() Create an annotation node

Insert node

    appendChild() Inserts the node at the end of the parent node
    insertBefore() Insert the node in front of a sibling node of the parent node

Delete node

    removeChild()

Find node

    getElementById()
    getElementsByTagName()
    getElementsByName()

Replace node

    replaceChild()

Write a method to format the time

function dateToString(date, format = 'yyyy-MM-dd') {
  const d = new Date(date);
  let result = format;
  const _config = {
    'y+': d.getFullYear(),
    'M+': d.getMonth() + 1, // month
    'd+': d.getDate(), // day
    'h+': d.getHours(), // hour
    'm+': d.getMinutes(), // branch
    's+': d.getSeconds(), // second
  };

  for (const reg in _config) {
    if (!(new RegExp(`(${reg})`).test(result))) continue;
    const match = RegExp.$1;
    let num = `${_config[reg]}`;
    while (num.length < match.length) { num = `0${num}` }
    result = result.replace(match, num);
  }

  return result;
}

function stringToDate(str, format = 'yyyy-MM-dd') {
  let args = [/y+/, /M+/, /d+/, /h+/, /m+/, /s+/];
  args = args.reduce((re, reg, index) => {
    const match = format.match(reg);
    const defaultValue = [1970, 0, 1, 0, 0, 0][index];
    if (!match) return re.concat([defaultValue]);
    var index = match.index;
    const num = Number(str.slice(index).match(/\d+/));
    return re.concat([num]);
  }, []);
  args.unshift(null);
  return new(Date.bind.apply(Date, args));
}

What is the difference between pjax and ajax?  

pjax It's a jQuery Plug in, it passes ajax and pushState Technology provides extremely fast (no refresh) ajax Load) browsing experience, and maintain the real address and web page title. The browser's back (forward) button can also be used normally.
pjax The working principle of is through ajax Get from server HTML,Use the obtained in the page HTML Replaces the contents of the specified container element. Then use pushState The current address in the address bar of the technology update browser. The following two reasons determine pjax Faster browsing experience:
No page resource exists( js/css)Repeated loading and application of;
If the server is configured pjax,It can render only part of the page, thus avoiding the additional overhead of the server rendering the complete layout.

Wechat applet realizes track playback, wechat native applet, and applet based on uniapp?

You need to write track drag, progress bar, start, pause and end functions.

What are the retry strategies for asynchronous requests?

Retry times, retry interval, etc

  Write a method to implement promise and retry automatically after failure

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

</body>

</html>
<script>
    Promise.retry = (fun, limit = 5) => {
        return new Promise((resolve, reject) => {
            let __num = 1;
            let __run = () => {
                fun()
                    .then(res => {
                        resolve(res);
                    })
                    .catch(err => {
                        if (__num++ >= limit) {
                            reject(err)
                        } else {
                            console.log('retry again!!')
                            __run()
                        }
                    })
            }
            __run()
        })
    }

    let k = 0

    function test() {
        return new Promise((resolve, reject) => {
            if (++k >= 3) {
                resolve(k)
            } else {
                reject('hhh')
            }
        })
    }

    Promise.retry(test).then(res => {
            console.log('resolve: ', res)
        }).catch(err => {
            console.log('reject: ', err)
        })
        // retry again!!
        // retry again!!
        // resolve: 3
</script>

  Operation results

Realize the effect of synthesizing multiple pictures into one  

The principle is to use canvas Canvas.

Before page loading mounted In the method:
 

    setTimeout(() => {
     
        this.changeimg();
     
    }, 1000);

changeimg( )method:

        changeimg(){
                var self = this;
                var imgsrcArray = [
                    require('../../assets/image/income/background.png'),
                    $('#qrcode canvas')[0].toDataURL('image/png')
                ];
                var canvas = document.createElement('canvas');
                var ctx = canvas.getContext('2d');
                canvas.width = 750;
                canvas.height = 1334;
                var imglen = imgsrcArray.length;
                var showContent = 'I am'+this.showPhone;
                var drawimg = (function f(n){
                    if(n < imglen){
                        var img = new Image();
                        img.crossOrigin = 'Anonymous'; //Solve cross domain problems
                        img.onload = function(){
                            if(n == 0){
                                ctx.drawImage(img,0,0,750,1334);
                                ctx.font = '30px Adobe Ming Std';
                                
                                ctx.fillText(showContent,250,800);
                                ctx.fillText('Text text',250,850);
                            }else{
                                ctx.drawImage(img,250,900,250,250);
                            }
                            f(n+1);
                        }
                        
                        img.src = imgsrcArray[n];
                    }else{
                        self.downloadUrl = canvas.toDataURL("image/jpeg");
                        self.downloadUrl = self.downloadUrl.replace("data:image/jpeg;base64,", "");
                    }
                })(0);
            }

In this example, a background image and a QR code image are combined into a picture ,

The generation of QR code also needs to be before this method.

html:

    <img style="width:100%;" :src="'data:image/jpeg;base64,' + downloadUrl" alt="">
    <div style="opacity:0;position:absolute;bottom:0;" id="qrcode"></div>

How does ajax receive pictures from the background?

1.set up responseType by Blob,2.take Blob Save as file

  What are the methods of js source code compression? What are their compression principles

method
1.Online tools
2.webpack

principle
1.Delete Note 
2.Variable name method name character reduction

Add without + eval Function
 

// Implementation using bitwise operators
function add (a, b) {
    if (a == 0 || b == 0) {
        return a || b;
    }
    while (b != 0) {
        let i = b;
        b = (a & b) << 1;
        a = a ^ i;
    }
    return a;
};

  Write an inverse method of document.querySelector

document.queryNode = function(node){
    if(node.id){
        return '#'+ node.id;
    }
    if(node.className){
        return '.'+ node.id;
    }
    return node.nodeName; 
};

How to determine whether an object belongs to a class?

    obj.proto === class.prototype You can find it recursively
    obj instanceof class

Tell me about your understanding of js sandbox. What application scenarios does it have?

Useful in micro front end js Sandbox, for example qiankun Framework, main application js Of running and subtasks js The operation will not affect each other, but use es6 of proxy To achieve

What is the relationship between pure function and functional programming?

Functional programming is a programming idea, and pure function is the basic of this idea

To realize functional programming, the methods we encapsulate should be abstract and independent of the external state, that is, they need to be pure functions, so as to ensure that the abstract methods can be reused, and the output results only depend on the input parameters.

Why use pure functions?  

Before that, you should first understand what pure functions are. In short, pure functions are defined in two ways:
1.The returned result depends only on the passed in parameters.
2.No side effects during execution.
Here we need to know what side effects are
1.Changed external variable or object properties
2.Trigger any external processes
3.send out http request
4.Call other functions with side effects
5.......
So why do we use pure functions? From the definition, we can know that no matter when you request a pure function, as long as the parameters are the same, the returned results must be the same.
Then, my understanding of side effects is that the function of a function should be single. You can't be responsible for calculation or any other behavior at the same time http Request something, initiate http The request should be implemented separately by another function.
Then, although the other function has side effects, its return result only depends on the incoming parameters (such as links). The benefits of this are convenient for testing and later maintenance. How can you take charge of multiple functions in a function? It's hard to look at this function later.

Use js to achieve a picture clipping function

/** 
 * Crop picture
 * @param imgUrl Original picture path
 * @param x,y,width,height Starting from point [x, y], cut the area with width and height
 * tips: You need to run in the server environment to cut the picture into the same domain
 */
function clipImage(imgUrl, x, y, width, height) {
    return new Promise((resolve, reject) => {
        let cvs = document.createElement("canvas");
        cvs.width = width;
        cvs.height = height;

        var ctx = cvs.getContext('2d');
        let _img = new Image();
        _img.src = imgUrl;
        _img.onload = () => {
            ctx.drawImage(_img, 0 - x, 0 - y);
            resolve(cvs.toDataURL());
        }
    })
}

clipImage("./img/loginbg.jpg", 100, 100, 300, 400).then(res => {
    let __img = document.createElement("img");
    __img.src = res;
    document.body.appendChild(__img);
})

Can the order of traversing objects be guaranteed by using the for in statement? If not, why? If so, how can we guarantee it?  

Chrome Opera of JavaScript The parsing engine follows the new version ECMA-262 Fifth edition specification. Therefore, use for-in Statement traverses an object property in a sequence other than the property construction sequence. and IE6 IE7 IE8 Firefox Safari of JavaScript The parsing engine follows older ECMA-262 In the third version of the specification, the order of attribute traversal is determined by the order of attribute construction.

If we need to output the attributes in a certain order, we can also save all the attributes in an array first key Value, sort the array, and finally loop through it key Array, by key Get the properties in the object:
var user = {};
if(!user['Jason']) {
user['Jason'] = [];
}
user['Jason']['grade'] = 3;
user['Jason']['level'] = 1;

if(!user['arthinking']) {
user['arthinking'] = [];
}
user['arthinking']['grade'] = 4;
user['arthinking']['level'] = 1;

console.log(user);

for(var key in user){
console.log('key: ', key);
}

var keys = [];
for(var key in user){
keys.push(key);
}
keys = keys.sort();

for(var i=0; i<keys.length; i++){
var key = keys[i];
console.log(user[key]['grade']);
}

Write a method to get the DPI of the screen  

 (function() {
	var arrDPI = new Array();
	if ( window.screen.deviceXDPI) {
		arrDPI[0] = window.screen.deviceXDPI;
		arrDPI[1] = window.screen.deviceYDPI;
	}
	else {
		var tmpNode = document.createElement( "DIV" );
		tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
		document.body.appendChild( tmpNode );
		arrDPI[0] = parseInt( tmpNode.offsetWidth );
		arrDPI[1] = parseInt( tmpNode.offsetHeight );
		tmpNode.parentNode.removeChild( tmpNode );
	}
	console.dir(arrDPI);
	return arrDPI;
})()

Whether the constructor of promise is executed synchronously or asynchronously, and its then method?

promise Constructors are executed synchronously, then Methods are executed asynchronously.

What is the difference between a memory leak and a memory overflow

Memory leak:Dynamic storage is used to allocate function memory space, which is not released after use, resulting in occupying the memory unit all the time,Until the end of the program.

out of memory:Local block size regardless of stack allocation,Too much data is written to the data block, resulting in data out of bounds,The result overwrites other data. Often occurs in recursion.

  Write a method to convert scientific counting into numbers or strings

function c(a) {
return a.replace(/^(\d+)(?:.(\d+))*eE(\d+)/,(_,a,a1,p,n)=>{
a1=a1||''
if(p==='-'&&n>0) {
return '0.'+'0'.repeat(n-1)+a+a1
}else{
return a+(a1.length>n? a1.substr(0, n)+'.'+a1.substr(n): a1+'0'.repeat(n-a1.length))
}
})
}

Write a method to verify whether the input value meets the amount format in real time, such as 3.56 (there are only two decimal places at most and only numbers and decimal points). Other special characters are not allowed to be input

<body>
  <input type="text" id="amount">
  <em id="message"></em>
</body>
<script>
  const amountInput = document.getElementById('amount');
  const msg = document.querySelector('#message');
  amountInput.oninput = function (event) {
    let value = event.target.value;
    let pat = /^\d+(\.\d{1,2})?$/;
    msg.innerHTML = pat.test(value) ? 'True' : 'False';
  }
</script>

Better way---input of pattern attribute

<input type="text" pattern="^\d+(\.\d{1,2})?$">

If you delete an array with delete, will its length change  

use delete If you delete an array element, will its length change?



Let's write a case🌰Just look at it:

var arr = [1, 2, 3]
delete arr[1]
console.log(arr)
console.log(arr.length)

The results are as follows:

Through the results, we can conclude that delete When you delete an array element, its length will not change.

In this regard, you can understand the array as a special object, and the pseudo code for converting each item into an object is:

key: value
// corresponding:
0: 1
1: 2
2: 3
length: 3

So we use delete When the operator deletes an array element, it is equivalent to removing an attribute in the array, and the deleted element no longer belongs to the array. However, this change does not affect the of the array length Properties.

Extension:

    If you want an array element to continue to exist, but its value is undefined,Then you can use undefined Assign to this element instead of using delete. For example: arr[1] = undefined
    If you want to remove an array element by changing the contents of the array, use splice() method. For example: arr.splice(1, 1)

  Will an exception be thrown if an undefined variable is encountered in the code? Will the program continue?

In the browser environment

JS Thrown when the parser resolves to an undefined variable Uncaught ReferenceError Wrong, JS The engine will stop parsing the following code, but the previous code will not be affected and jump out of the code block.

Let's look at the specific code.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>
Will an exception be thrown if an undefined variable is encountered in the code? Will the program continue
    </title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
  </head>
  <body>
    <script>
      console.log(1);
    </script>
    <script>
      console.log(2);
      console.log(a);
      console.log(3);
    </script>
    <script>
      console.log(4);
    </script>
  </body>
</html>

    JS The engine loads the first one first<script></script> Code block, enter the three processes of parsing(1,Lexical grammar analysis, 2. Pre parsing, 3. Execution phase),Then output 1 on the console;
    next JS The engine loads the second<script></script> Code block, enter the three processes of parsing, and the console outputs 2 when parsing console.log(a); This line of code, because a Is an undefined variable and will be thrown Uncaught ReferenceError Wrong, JS The engine will stop parsing the following code, that is JS The engine will not execute console.log(3); This line of code and jump out of the second one<script></script> Code block;
    Load the third one immediately<script></script> Code block, enter the three processes of parsing, and output 4 on the console.

Tell me about your understanding of JSBridge

js And native applications

  How do we call asynchronous methods in the js loop to ensure that the order of execution results is correct?

An example:

let searchApi = function(arg){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log(arg)
            resolve(arg)
        }, 20)
    })
};
let fields = [1,2,3,4];
let arr = new Array(fields.length);
await fields.forEach(async (vvv, index) => {
    const obj = await searchApi(vvv)
    arr[index] = obj
    const tempArr = JSON.parse(JSON.stringify(arr))
    if(tempArr.every(Boolean)){
        console.log(arr)
    }
})

Write a method to traverse all the properties of the specified object

Object.keys(),Object.values()You can only traverse the object's own properties, for in You can traverse the properties in the prototype.

Method of realizing a function memory

Synchronous operation result caching is an old saying:

function useCache(func) {
  var cache = {};
  return function() {
    var key = arguments.length + Array.prototype.join.call(arguments);
    if(cache[key]) return cache[key];
    cache[key] = func.apply(this, arguments);
    return cache[key];
  }
}

Handwritten a trim() method  

function trim(str) {
if (str[0] === ' ' && str[str.length - 1] === ' ') {
return trim(str.substring(1, str.length - 1))
} else if (str[0] !== ' ' && str[str.length - 1] === ' ') {
return trim(str.substring(0, str.length - 1))
} else if (str[0] === ' ' && str[str.length - 1] !== ' ') {
return trim(str.substring(1, str.length))
} else if (str[0] !== ' ' && str[str.length - 1] !== ' ') {
return str;
}
}

How do you compare the execution speed of js functions?  

use chrome performance api


console.time(flag);
console.timeEnd(flag);


performance api More accurate
console.time(flag);
You can match it timelog Multiple measurements

What is the principle of axios interceptor?

The interceptor principle is actually to add user-defined functions to the interceptor array with use.
Finally, put them before and after the interceptor request. Make up promise chain call.

  // Form a 'Promise' chain
  // Hook up interceptors middleware
  // Put the dispatchRequest and undefined of the xhr request into an array
  var chain = [dispatchRequest, undefined];
  // Create Promise instance
  var promise = Promise.resolve(config);

 // Traverse the request interceptor set by the user and put it in front of the chain of the array
  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

 // Traverse the response interceptor set by the user and put it after the chain of the array
  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

 // Traverse the chain array until the chain.length is 0
  while (chain.length) {
    // Move them out in pairs and put them in the two parameters of then.
    promise = promise.then(chain.shift(), chain.shift());
  }

  return promise;

Is the principle of fetch and axios requests based on xmlhttprequst?

axios Is based on XMLHttpRequest Packaging, and fetch yes js Native supported network requests api,This is supported at the bottom of the browser.

What are the disadvantages of object-oriented programming?

There is instantiation overhead, which consumes a lot of memory and performance

Using js to implement a circular queue  

const queue = []
let queueRunning = false
let loopTimer = null
const loop = task => {
  // do something...
  console.log(task)
  if (isQueueHasTask()) {
    // you can add new tasks in the middle of the queue.
    loopTimer = setTimeout(() => {loop(getNextTask())})
  } else {
    queueRunning = false
  }
}
const startLoop = () => {
  if (queueRunning) return
  if (isQueueHasTask()) {
    queueRunning = true
    loop(getNextTask())
  }
}
const stopLoop = () => {
  if (!queueRunning) return
  if (loopTimer) {
    clearTimeout(loopTimer)
    queueRunning = false
  }
}
const getNextTask = () => queue.shift()
const isQueueHasTask = () => !!queue.length
const addTask = task => {
  if (!Array.isArray(task)) task = [task]
  queue.push(...task)
  startLoop()
}

What is the storage space of Number()? What if the interface returns a number that exceeds the maximum byte?  

Number The maximum value of type is the 53rd power of 2, i.e. 9007199254740992. If it exceeds this value, such as 90071992547409222, the obtained value will be inaccurate, i.e. 900719925474099200

How does alert wrap text?

Consider compatibility before using escape characters
ie:  alert("A\r\nB"); //chrome can also be implemented
chrome:  alert("A\nB");

How many times does an api interface interact with the server from requesting data to the end of the request?

 API It refers to some predefined functions or conventions for the connection of different components of the software system.
    If a connection has been established, a single request for data to the end of the request should be an interaction;
    If the connection is not established, it may be different according to the protocol, such as ajax Polling and websocket There is a difference in the data flow after establishing a connection with the server

What are the loop structures of js?

for
for in
while
do while

What are the disadvantages of innerHTML?

innerHTML The old content in the element will be removed and the new content will be rewritten to the element. innerHTML The content will be re parsed and the element will be built. for example
innerHTML+ = "" When the content is "zeroed" and rewritten, all pictures and resources are reloaded, which will consume more time.

Give an example of what tail call optimization is in js

Write in front
Last time, I introduced what is a tail call and how to accurately and quickly judge whether a function call is a tail call. So, what is the meaning of distinguishing tail calls? There is always a purpose to do anything, so today we will systematically introduce the meaning of tail call, or what is the use of tail call.

2. Tail call optimization

As we know, the call of a function will generate a "call frame" in memory, which stores the call location and internal variables of the function. If function B is called inside function a, a call frame of B will be generated above the call frame of A. When function B finishes running and returns the result to a, the call frame of B will disappear. If function C is also called inside function B, a call frame of C will be generated above the call frame of B, and so on. All call frames form a call stack.

We know that the tail call is the last operation of the function, and the call position of the external function and its internal variable information will not be used again, so there is no need to retain the call frame of the external function, and the call frame of the outer function can be directly replaced by the call frame of the inner function.

If all functions are tail calls, it can be achieved that there is only one call frame during each execution, which will greatly save memory and prevent memory overflow. This is the significance of discussing tail calls.

The so-called "tail call optimization" is actually to ensure that only the call frame of the inner function is retained during function execution. In other words, the call frame of the outer function is replaced by the call frame of the inner function, that is, only one call frame is saved in memory during execution.
3. How to optimize tail call

From the above discussion, we know that "tail call optimization" can be achieved as long as the call frame of the external function is replaced by the call frame of the inner function. At the same time, we also know that the call frame is used to save the function call location and internal variable information. Therefore, if you want the call frame of the inner function to replace the call frame of the external function, you only need to ensure that all information related to the external function is not used when calling the inner function (the internal variables of the external function are not used).

In this way, we conclude that "tail call optimization" can be achieved only if the internal variables of the external function are no longer used when the inner function is called.

Let's start with an example:

function f(a) {
    var b = 3;
    function g(n) {
      return n + b
    }
    return g(a)
}


In the above example, we can clearly see that this is a typical tail call. Does this achieve "tail call optimization"? Obviously, it can be seen that when calling the internal function g, the internal variable b of the external function f is used internally. Therefore, when the function g is called, the call frame of G cannot replace the call frame of the external function f, so this is not "tail call optimization".

How to judge whether two objects are equal?

Provide another way to write:

function isSameObject(object1, object2) {
    if (Object.prototype.toString.call(object1) === '[object Object]' &&
        Object.prototype.toString.call(object2) === '[object Object]') {
        if (Object.keys(object1).length !== Object.keys(object2).length) {
            return false;
        }
        for (let key in object1) {
            if (!object2[key] || object1[key] !== object2[key]) {
                return false;
            }
        }
    }
    return true;
}

Of course, JSON.stringify(obj)==JSON.stringify(obj) is the fastest
 

  What are the ways of string splicing? Which performance is good?

1.use + number
2.es6 Template string, in backquotes( ` )identification
3.concat
4.Array method join

The best performance is connectivity: +
Continue to add:

    Array.prototype.reduce
    String.prototype.padStart
    String.prototype.padEnd

When does localStorage expire?

By default, it will not expire unless you know the browser cache or delete it manually setItem The cache time parameter is used to compare the time before and after taking it out. If the time limit is exceeded, the cache can be deleted.

Write a method to get a non interlaced style

window.getComputedStyle()?window.getComputedStyle(element).attribute:element.currentStyle.attribute

Write a method to get all checkbox es in the page

function getAllCheckbox() {
  return [...document.querySelectorAll('input[type=checkbox]')]
}

  What is the difference between XML and JSON?

xml Can set id,use include And the like can be directly referenced, and even the content format can be agreed.
but json Not dependent js It will be difficult to complete the language.

Well, broadly speaking,
json Compilation is simpler and easier to understand, smaller, less complex, and easier to transmit.
xml There are agreed standards or formats, and the feeling of attribute structure is stronger.

The different feeling of this structure can be seen below

<country>
  <name>China</name>
  <province>
    <name>Hubei</name>
    <citys>
     <city>Wuhan</city>
    </citys>
  </province>
  <nation>
    <name>Han nationality</name>
  </nation>
  <nation>
    <name>Zhuang Nationality</name>
  </nation>
</country>

{
  "name": "China",
  "provinces": [
    {
      "name": "Hubei",
      "citys": [
        {
          "city": "Wuhan" 
        }
      ]
    }
  ],
  "nation": [
    {
      "name": "Han nationality"
    },
    {
      "name": "Zhuang Nationality"
    }
  ]
}



xml Is a markup extensible language, JSON(javascript object notation)Is based on javascript A subset of, xml than json It has a clearer hierarchy, but needs more characters to describe, json than xml More popular.

How does flash interact with js?

When Flash put HTML When in a container, it is often encountered AS And JS Communication problems, such as: JS Can I call AS Variables and methods in, AS Can I call JS The answer is yes. With the continuous development of technology, there are many solutions.
In my summary HTML And FLASH The "static" value transfer between is mentioned in the article JS use SetVariable Method to set FLASH Variables in, kinglong I agree that this law is outdated, but the point above is not to discuss it after all JS And AS Therefore, in addition AS And JS Communication to make a personal summary, welcome to discuss.
realization JS Follow AS At present, there are many optional methods for communication, but the early methods are not perfect in terms of convenience and function. The following is a brief description:
  I getURL  getURL("javascript:history.go(-1)");

adopt URL Protocol to access javascript,The above code controlling the browser history is familiar. For example, we often use this method when customizing the page collection and sending e-mail. Although you can also call the code defined in the page JS Function, but I personally think it has great limitations. The parameter transfer of the function is not very flexible, has no return value, and can only be implemented AS call JS,Not vice versa.

  II fscommand command
 use fscommand To call AS The method of definition is also a very common way, but we need to HTML Define a page with a specified format myFlash_DoFSCommand Function, I personally find it troublesome to define this function first, and it can only be implemented AS call JS,No function return value.

  III SetVariable  
Both of the above methods can only be implemented AS call JS,and SetVariable On the contrary, as long as we do a little processing, he can help us call in disguise AS The general idea is as follows: AS Set a state variable in and use Object of watch Method to monitor it, JS adopt SetVariable To modify the state variable. Once the change of the variable is detected, it can be selected according to different state values AS If you need to consider the user's low version player, you can consider this method. Personally, I think it is more flexible.

  It can be seen that the above methods have certain limitations, so we have to use them together in our applications. What I want to introduce in detail below is ExternalInterface Through it, you can easily achieve AS And JS Two way method call, which also solves the two-way variable access. For details, see FLASH Help documentation and Adobe The following two simple examples are used to illustrate the official tutorial of ExternalInterface Use of.

I AS call JS Method of(Example demonstration)

Flash Medium code:
//Import package
import flash.external.*;
get_btn.onRelease = function(){
//Call the JS function in the page
var temp_str = String(ExternalInterface.call("say", "Hello,World"));
result_txt.text = temp_str;
}
Html Medium code: function say(txt){
return txt;
}

Yes, it's that simple, JS The function definition has no requirements, AS Used in call Method can be called directly.

II JS call AS Method of(Example demonstration)

FLASH Medium code://Import package
import flash.external.*;
//Provide the function name accessed by JS
var _method:String = "say";
//Specify the scope of this variable in the local function, which can be set to null and left blank
var e_area:Object = null;
//AS internal function name
var method:Function = say;
//Register function to container list
var wasSuccessful:Boolean = ExternalInterface.addCallback(_method, e_area, method);
//Check whether the registration is successful
if(wasSuccessful){
result_txt.text = "Function registration succeeded";
}
//Local function
function say(txt:String) {
result_txt.text = txt;
}
Html Medium code:<div>
<form>
<input type="button" οnclick="callExternalInterface()" value="JS call AS method" />
</form>
<script>
function callExternalInterface() {
thisMovie("demo").say("Hello,World");
}
//Browser compatible access to DOM
function thisMovie(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName]
}
else {
return document[movieName]
}
}
</script>
</div>
The red code is the core code, and its function principle is AS End pass addCallback Function handle AS The internally defined method is registered to be invoked from the container, allowing another method name to be supplied. JS To call this method, and the function call returns successfully true,Failure Return flase,In this case, by wasSuccessful Variable to determine whether the function is successfully registered. After the function is registered successfully, JS Can pass DOM To visit SWF Object, and then directly call the predefined methods.

Through comparison, it can be seen that ExternalInterface To complete AS and JS The code can be simpler, clearer and more powerful, but there are still some details you need to understand and use 8.0 The above player, for the called JS Functions cannot use recursion, and security domain restrictions must be taken into account.

Tell me about your understanding of js object life cycle

start


Everything is an object

We often hear "everything is an object" in JS? Have you ever wondered what this means? Other languages also have the saying that "everything is an object", such as python. But objects in Python are not just containers for storing values and values like JS objects. An object in Python is a class. There are similar things in JS, but the "object" in JS is only a container for keys and values:

var obj = { name: "Tom", age: 34 }

In fact, the object in JS is a "dumb" type, but many other entities seem to be derived from the object. Even arrays. Create an array in JS, as shown below:

var arr = [1,2,3,4,5]

Then check the type with the typeof operator, and you will see a surprising result:

typeof arr
"object"

It seems that array is a special object! Even functions in JS are objects. If you dig deeper and there are more, create a function, which will attach some methods:

var a = function(){ return false; }
a.toString()
1
2
Output:

"function(){ return false; }"

We didn't declare the toString method in the function, so there must be something at the bottom. Where did it come from? Object has a method named. ToString. It seems that our function has the same object method.

Object.toString()

At this time, we use the browser console to view the attached functions and properties by default, and the mystery will become more complex:

640?wx_fmt=png

Who put these methods in functions. The function in JS is a special object. Is this a hint? Look at the picture above: our function has a strange named attribute named prototype. What the hell is this?

The prototype in JS is an object. It is like a backpack, attached to most JS built-in objects. For example, object, function, array, date and error all have a "prototype":

typeof Object.prototype // 'object'
typeof Date.prototype // 'object'
typeof String.prototype // 'object'
typeof Number.prototype // 'object'
typeof Array.prototype // 'object'
typeof Error.prototype // 'object'

Note that the built-in object has uppercase letters:

String

Number

Boolean

Object

Symbol

Null

Undefined

The following are the basic types of JS except Object. On the other hand, built-in objects, like JS type images, are also used as functions. For example, you can use String as a function to convert a number to a String:

String(34)

Now back to "prototype". Prototype is the host of all public methods and properties, and "child" objects derived from ancestors can use ancestral methods and properties. In other words, given an original prototype, we can create new objects. These objects will use a prototype as the real source of the public function, not look see.

Suppose you have a request to create a chat application with a person object. This character can send messages and receive a greeting when logging in.

According to the requirements, we can easily define this Person object:

var Person = {
  name: "noname",
  age: 0,
  greet: function() {
    console.log(`Hello ${this.name}`);
  }
};

You may want to know why the Person object is declared in a literal way. As will be described in detail later, the Person is now "model". Through this model, we use Object.create() to create objects based on this model.
Create and link objects

Objects in JS seem to be linked together in some way. Object.create() illustrates this. This method creates a new object from the original object, and then creates a new Person object:

var Person = {
  name: "noname",
  age: 0,
  greet: function() {
    console.log(`Hello ${this.name}`);
  }
};
 
var Tom = Object.create(Person);

Now, Tom is a new object, but we don't specify any new methods or properties, but it can still access the name and age properties in Person.

var Person = {
  name: "noname",
  age: 0,
  greet: function() {
    console.log(`Hello ${this.name}`);
  }
};
 
var Tom = Object.create(Person);
 
var tomAge = Tom.age;
var tomName = Tom.name;
 
console.log(`${tomAge} ${tomName}`);
 
// Output: 0 noname

Now, you can create a new person from a common ancestor. Strangely, however, the new object remains connected to the original object, which is not a big problem because "child" objects can customize properties and methods

var Person = {
  name: "noname",
  age: 0,
  greet: function() {
    console.log(`Hello ${this.name}`);
  }
};
 
var Tom = Object.create(Person);
 
Tom.age = 34;
Tom.name = "Tom";
var tomAge = Tom.age;
var tomName = Tom.name;
 
console.log(`${tomAge} ${tomName}`);
 
// Output: 34 Tom

This approach is called "masking" the original attributes. There is another way to pass properties to new objects. Object.create takes another object as the second parameter, where you can specify keys and values for the new object:

var Tom = Object.create(Person, {
  age: {
    value: 34
  },
  name: {
    value: "Tom"
  }
});

Properties configured in this way are not writable, enumerable and configurable by default. Not writable means that the property cannot be changed later, and the change will be ignored:

var Tom = Object.create(Person, {
  age: {
    value: 34
  },
  name: {
    value: "Tom"
  }
});
 
Tom.age = 80;
Tom.name = "evilchange";
 
var tomAge = Tom.age;
var tomName = Tom.name;
 
Tom.greet();
 
console.log(`${tomAge} ${tomName}`);
 
// Hello Tom
// 34 Tom

Non enumeration means that the attribute will not be displayed in the for... In loop, for example:

for (const key in Tom) {
  console.log(key);
}
 
// Output: greet

But as we can see, because the JS engine looks up along the prototype chain, it finds the greet attribute on the "parent" object. Finally, non configurability means that properties can neither be modified nor deleted.

Tom.age = 80;
Tom.name = "evilchange";
delete Tom.name;
var tomAge = Tom.age;
var tomName = Tom.name;
 
console.log(`${tomAge} ${tomName}`);
 
// 34 Tom

If you want to change the behavior of attributes, you only need to configure writable, configurable and enumerable attributes.

var Tom = Object.create(Person, {
  age: {
    value: 34,
    enumerable: true,
    writable: true,
    configurable: true
  },
  name: {
    value: "Tom",
    enumerable: true,
    writable: true,
    configurable: true
  }
});

Now, Tom can also access greet() in the following ways:

var Person = {
  name: "noname",
  age: 0,
  greet: function() {
    console.log(`Hello ${this.name}`);
  }
};
 
var Tom = Object.create(Person);
 
Tom.age = 34;
Tom.name = "Tom";
var tomAge = Tom.age;
var tomName = Tom.name;
Tom.greet();
 
console.log(`${tomAge} ${tomName}`);
 
// Hello Tom
// 34 Tom

Don't worry too much about "this" for the time being. Pull it down and I'll explain it in detail. For now, remember that "this" is a reference to an object executed by a function. In our example, greet() runs in the context of Tom, so you can access "this.name".
Building JavaScript objects

So far, I've only introduced a little knowledge about "prototype" and played for a while except Object.create(), but we didn't use it directly. Over time, a new pattern has emerged: constructors. It sounds reasonable to use a function to create a new object. Assuming you want to convert a Person object into a function, you can use the following methods:

function Person(name, age) {
  var newPerson = {};
  newPerson.age = age;
  newPerson.name = name;
  newPerson.greet = function() {
    console.log("Hello " + newPerson.name);
  };
  return newPerson;
}

Therefore, there is no need to call object.create() everywhere, just call Person as a function:

var me = Person("Valentino");

The constructor pattern helps to encapsulate the creation and configuration of a series of JS objects. Here, we use literal methods to create objects. This is a convention borrowed from object-oriented languages, where class names start with uppercase.

The above example has a serious problem: every time we create a new object, we repeatedly create the greet() function again and again. You can use Object.create(), which creates links between objects only once. First, let's move the greet() method to an outside object. You can then link the new object to the public object using Object.create():

var personMethods = {
  greet: function() {
    console.log("Hello " + this.name);
  }
};
 
function Person(name, age) {
  // greet lives outside now
  var newPerson = Object.create(personMethods);
  newPerson.age = age;
  newPerson.name = name;
  return newPerson;
}
 
var me = Person("Valentino");
me.greet();
 
// Output: "Hello Valentino"

This method is a little better than at the beginning, and can be further optimized. It is to use prototype. Prototype is an object on which you can extend properties, methods, etc.

Person.prototype.greet = function() {
  console.log("Hello " + this.name);
};

Removed personMethods. Adjust the parameters of Object.create, otherwise the new object will not be automatically linked to the common ancestor:

function Person(name, age) {
  // greet lives outside now
  var newPerson = Object.create(Person.prototype);
  newPerson.age = age;
  newPerson.name = name;
  return newPerson;
}
 
Person.prototype.greet = function() {
  console.log("Hello " + this.name);
};
 
var me = Person("Valentino");
me.greet();
 
// Output: "Hello Valentino"

Now the source of the public method is Person.prototype. Using the new operator in JS, you can eliminate all noise in Person, and you only need to assign parameters to this.

The following code:

function Person(name, age) {
  // greet lives outside now
  var newPerson = Object.create(Person.prototype);
  newPerson.age = age;
  newPerson.name = name;
  return newPerson;
}
 

Change to:  

function Person(name, age) {
  this.name = name;
  this.age = age;
}



Full code:

function Person(name, age) {
  this.name = name;
  this.age = age;
}
 
Person.prototype.greet = function() {
  console.log("Hello " + this.name);
};
 
var me = new Person("Valentino");
me.greet();
 
// Output: "Hello Valentino"


Note that using the new keyword, called "constructor call", new does three things

Create an empty object

Point the proto of the empty object to the prototype of the constructor

Call constructor with empty object as context

function Person(name, age) {

According to the above description, new Person("Valentino") did:

Create an empty object: var obj = {}

The proto of an empty object__` Prototype pointing to constructor: ` obj__ proto = Person().prototype

Call constructor with empty object as context: Person.call(obj)

Check prototype chain

There are many ways to check the prototype links between JS objects. For example, Object.getPrototypeOf is a method that returns the prototype of any given object. Consider the following codes:

var Person = {
  name: "noname",
  age: 0,
  greet: function() {
    console.log(`Hello ${this.name}`);
  }
};
 
var Tom = Object.create(Person);

inspect Person Is it Tom Prototype:

var tomPrototype = Object.getPrototypeOf(Tom);
 
console.log(tomPrototype === Person);
 
// Output: true



Of course, if you use constructor calls to construct objects, Object.getPrototypeOf can also work. However, you should check the prototype object, not the constructor itself:

function Person(name, age) {
  this.name = name;
  this.age = age;
}
 
Person.prototype.greet = function() {
  console.log("Hello " + this.name);
};
 
var me = new Person("Valentino");
 
var mePrototype = Object.getPrototypeOf(me);
 
console.log(mePrototype === Person.prototype);
 
// Output: true



In addition to Object.getPrototypeOf, there is another method isPrototypeOf. This method is used to test whether an object exists on the prototype chain of another object. As shown below, check whether me is on Person.prototype:

Person.prototype.isPrototypeOf(me) && console.log('Yes I am!')

The instanceof operator can also be used to test whether the prototype property of the constructor appears anywhere in the prototype chain of the object. To be honest, this name is a bit misleading because there is no "instance" in JS. In a true object-oriented language, an instance is a new object created from a class. Consider the example in Python. We have a class named Person, from which we create a new instance named "tom":

class Person():
    def __init__(self, age, name):
        self.age = age;
        self.name = name;
 
    def __str__(self):
        return f'{self.name}'
 
 
tom = Person(34, 'Tom')



Note that there is no new keyword in Python. Now, we can use the isinstance method to check whether tom is an instance of Person

isinstance(tom, Person)
 
// Output: True

Tom Also Python Medium“ object"The following code also returns an instance of true: 

isinstance(tom, object)
 
// Output: True



According to the isinstance document, "if the object parameter is an instance of a class parameter or an instance of its (direct, indirect or virtual) subclass, it returns true". We are talking about the class here. Now let's see what instanceof does. We will start with the Person function in JS to create Tom (because there is no real class)

function Person(name, age) {
  this.name = name;
  this.age = age;
}
 
Person.prototype.greet = function() {
  console.log(`Hello ${this.name}`);
};
 
var tom = new Person(34, "Tom");



Use the isinstance method to check whether tom is an instance of Person and Object

if (tom instanceof Object) {
  console.log("Yes I am!");
}
 
if (tom instanceof Person) {
  console.log("Yes I am!");



Therefore, it can be concluded that the prototype of JS objects is always connected to the direct "parent object" and Object.prototype. There is no class like Python or Java. JS is composed of objects, so what is the prototype chain? If you pay attention, we mentioned the "prototype chain" several times . it seems amazing that JS objects can access methods defined elsewhere in the code. Consider the following example again:

var Person = {
  name: "noname",
  age: 0,
  greet: function() {
    console.log(`Hello ${this.name}`);
  }
};
 
var Tom = Object.create(Person);
 
Tom.greet();



Even if the method does not exist directly on the "Tom" object, Tom can access greet().

This is an inherent feature of JS, which borrows the prototype system from another language called Self. When accessing greet(), the JS engine will check whether the method can be used directly on Tom. If not, the search will continue to link up until the method is found.

"Chain" is the hierarchy of prototype objects connected by Tom. In our example, Tom is an Object of type Person, so Tom's prototype is connected to Person.prototype. While Person.prototype is an Object of type Object, so it shares the same Object.prototype prototype. If there is no greet() on Person.prototype , the search will continue to link up until it reaches Object.prototype. This is what we call the "prototype chain".
Protect objects from manipulation

In most cases, JS object "extensibility" is necessary so that we can add new properties to the object. However, in some cases, we want the object not to be further manipulated. Consider a simple object:

var superImportantObject = {
  property1: "some string",
  property2: "some other string"
};



By default, everyone can add new properties to the object

var superImportantObject = {
  property1: "some string",
  property2: "some other string"
};
 
superImportantObject.anotherProperty = "Hei!";
 
console.log(superImportantObject.anotherProperty); // Hei!

Object.preventExtensions()Method makes an object non extensible, that is, you can never add new properties.

var superImportantObject = {
  property1: "some string",
  property2: "some other string"
};
 
Object.preventExtensions(superImportantObject);
 
superImportantObject.anotherProperty = "Hei!";
 
console.log(superImportantObject.anotherProperty); // undefined



This technology is very convenient for "protecting" key objects in code. There are many pre created objects in JS, which are closed for extension, so as to prevent developers from adding new properties to these objects. This is the case of "important" objects, such as the response of XMLHttpRequest. Browser vendors prohibit adding new properties to response objects

var request = new XMLHttpRequest();
request.open("GET", "https://jsonplaceholder.typicode.com/posts");
request.send();
request.onload = function() {
  this.response.arbitraryProp = "I am a newly added attribute";
  console.log(this.response.arbitraryProp); // undefined
};



This is done by calling Object.preventExtensions internally on the 'response' object. You can also use the Object.isExtensible method to check whether the object is protected. If the object is extensible, it will return true:

var superImportantObject = {
  property1: "some string",
  property2: "some other string"
};
 
Object.isExtensible(superImportantObject) && console.log("I am scalable");



If the object is not extensible, it returns false:

var superImportantObject = {
  property1: "some string",
  property2: "some other string"
};
 
Object.preventExtensions(superImportantObject);
 
Object.isExtensible(superImportantObject) ||
  console.log("I am not extensible!");



Of course, the existing properties of an object can be changed or even deleted

var superImportantObject = {
  property1: "some string",
  property2: "some other string"
};
 
Object.preventExtensions(superImportantObject);
 
delete superImportantObject.property1;
 
superImportantObject.property2 = "yeees";
 
console.log(superImportantObject); // { property2: 'yeees' }



Now, in order to prevent this operation, each property can be defined as non writable and non configurable. For this purpose, there is a method called Object.defineProperties.

var superImportantObject = {};
 
Object.defineProperties(superImportantObject, {
  property1: {
    configurable: false,
    writable: false,
    enumerable: true,
    value: "some string"
  },
  property2: {
    configurable: false,
    writable: false,
    enumerable: true,
    value: "some other string"
  }
});



Or, more conveniently, you can use object.free on the original object:

var superImportantObject = {
  property1: "some string",
  property2: "some other string"
};
 
Object.freeze(superImportantObject);



Object.free works in the same way as Object.preventExtensions, and it makes the properties of all objects non writable and non configurable. The only disadvantage is that "object. Free" is only applicable to the first level of objects: nested objects are not affected by operations.
class

There are a lot of articles about ES6 classes, so only a few points are discussed here. Is JS a real object-oriented language? It seems so. If we look at this code

class Person {
  constructor(name) {
    this.name = name;
  }
 
  greet() {
    console.log(`Hello ${this.name}`);
  }
}



The syntax is very similar to classes in other programming languages such as Python:

class Person:
    def __init__(self, name):
        self.name = name
 
    def greet(self):
        return 'Hello' + self.name



Or PHP

class Person {
    public $name; 
 
    public function __construct($name){
        $this->name = $name;
    }
 
    public function greet(){
        echo 'Hello ' . $this->name;
    }
}



Classes are introduced in ES6. But at this point, we should be clear that there is no "real" class in JS. Everything is just an object. Despite the keyword class, the "prototype system" still exists. The new JS version is backward compatible, which means that new functions have been added on the basis of existing functions. Most of these new functions are syntax sugar of legacy code.
summary

Almost everything in JS is an object. Literally. JS objects are containers for keys and values, and may also contain functions. Object is the basic building block in JS: therefore, you can create other custom objects from a common ancestor. Then we can link objects together through the internal characteristics of language: prototype system.

Starting with a public object, you can create other objects that share the same properties and methods as the original "parent". But it doesn't work by copying methods and properties to every child, just like the OOP language. In JS, each derived object maintains a connection with the parent object. Use Object.create or use the so-called constructor to create a new custom object. Paired with the new keyword, the constructor is similar to imitating a traditional OOP class.
reflection

How to create immutable JS objects?

What is a constructor call?

What is a constructor?

What is "prototype"?

Can you describe what new has done at the bottom?

The bugs that may exist after code deployment cannot be known in real time. Afterwards, in order to solve these bugs, we spent a lot of time on log debugging. By the way, we recommend a useful BUG monitoring tool Fundebug.
 

END

Bind two click events (one with capture and one with bubble) on the DOM at the same time. How many times will the event be executed in total? Which event will be executed first?

twice
 Capture first, then bubble

What is the difference between json and object?

JSON Is an object, but the object is not necessarily an object JSON. 

Objects are composed of attributes and attribute values, that is KEY->VALUE yes.
Object value Can be any data type, including functions. and JSON Medium value Cannot be a function.

Will the location of the script affect the first screen display time

Yes, if script On the head, js The execution of will block dom Construction of tree

  What is the difference and function between callee and caller?

arguments.callee Refers to the current function
Function.caller Refers to the function that calls the current function
 for instance:

function a() {
  console.log(arguments.callee);
  console.log(a.caller); 
}
function b() {
  a();
}
b();
a();

Console output:
[Function: a]
[Function: b]
[Function: a]
null

Function: it can be used in situations where function self calling or parent function calling is required

What application scenarios does AudioContext have?  

AudioContext Examples are createAnalyzer(),Can achieve audio visualization, there is another gainNode,Input can be realized(MediaStream or HTMLMediaElement)Volume range adjustment

Write a method to get the direction of the picture

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title></title>
<script>
function getOrientation(file, callback) {
var reader = new FileReader();
reader.onload = function(e) {

var view = new DataView(e.target.result);
if (view.getUint16(0, false) != 0xFFD8)
{
return callback(-2);
}
var length = view.byteLength, offset = 2;
while (offset < length)
{
if (view.getUint16(offset+2, false) <= 8) return callback(-1);
var marker = view.getUint16(offset, false);
offset += 2;
if (marker == 0xFFE1)
{
if (view.getUint32(offset += 2, false) != 0x45786966)
{
return callback(-1);
}

var little = view.getUint16(offset += 6, false) == 0x4949;
offset += view.getUint32(offset + 4, little);
var tags = view.getUint16(offset, little);
offset += 2;
for (var i = 0; i < tags; i++)
{
if (view.getUint16(offset + (i * 12), little) == 0x0112)
{
return callback(view.getUint16(offset + (i * 12) + 8, little));
}
}
}
else if ((marker & 0xFF00) != 0xFF00)
{
break;
}
else
{
offset += view.getUint16(offset, false);
}
}
return callback(-1);
};
reader.readAsArrayBuffer(file);
}
window.onload = function(){
var input = document.getElementById('input');
input.onchange = function(e) {
getOrientation(input.files[0], function(orientation) {
alert('orientation: ' + orientation);
});
}
};
</script>
</head>
<body>
<input id='input' type='file' />
</body>
</html>

After setting the keyup listening event, what is the difference between pressing F5 to refresh and pressing the refresh key in the browser to refresh?

Pressing the refresh key in the browser will not trigger refresh keyup event

  Write a method in js to check whether the browser supports the properties of css3

var div = document.createElement('div');
console.log(div.style.transition);
//If supported, it will output ""
//If it is not supported, it will output undefined


For a = = ('1 '|'2' |'3 ')? False: improve the writing method of true and write your optimized method

![1,2,3].includes(+a)
or
!['1', '2', '3'].includes(a + '')
or
!{1: true, 2: true, 3: true}[a]

  What is Geolocation.getCurrentPosition() used for? In what browsers are incompatible?

Gets the location of the current device
Android I won't support it

What's the use of the third parameter of setTimeout?

The third parameter will be the parameter of the function triggered by timer expiration

Explain the difference between depth first traversal and breadth first traversal and how to implement them

1,Depth priority adopts stack structure, first in and last out, which occupies less space and takes longer execution time;
2,Breadth first adopts the queue structure of first in first out, which occupies a large space, short execution time and space for time;

const data = [
        {
            name: 'a',
            children: [
                { name: 'b', children: [{ name: 'e' }] },
                { name: 'c', children: [{ name: 'f' }] },
                { name: 'd', children: [{ name: 'g' }] },
            ],
        },
        {
            name: 'a2',
            children: [
                { name: 'b2', children: [{ name: 'e2' }] },
                { name: 'c2', children: [{ name: 'f2' }] },
                { name: 'd2', children: [{ name: 'g2' }] },
            ],
        }
    ]

    //Depth first
    function byDeepth(data) {
        let result = []
        const map = (item) => {
            result.push(item.name)
            item.children && item.children.forEach((item) => map(item))
        }
        data.forEach((item) => {
            map(item)
        })
        return result.join(',')
    }

    //Breadth first
    function byBreadth(data) {
        let result = []
        let queque = data
        while (queque.length > 0) {
            result.push(queque[0].name)
            if (queque[0].children) {
                queque = queque.concat(queque[0].children)
            }
            queque.shift()
        }
        return result.join(',')
    }
    console.time('Depth first')
    console.log('Depth first', byDeepth(data))
    console.timeEnd('Depth first')

    console.time('Breadth first')
    console.log('Breadth first', byBreadth(data))
    console.timeEnd('Breadth first')

What do you think are the design defects of es5?

You can think the other way around, es6 The new feature is to solve the problem es5 Design defects

  What are the advantages and disadvantages of using the ajax polling interface?

First, the principle of the so-called polling interface is to use setTimeout Timing request API Interface

advantage:
1,It can be simple without secondary development websocket There is almost no learning cost to achieve the required functions
2,Easy to use
 Disadvantages:
1,Relative performance socket Relatively poor, use setTimeout The timing request interface occupies memory performance, and the timing task may request timeout, resulting in memory overflow
2,The data returned by the request is unstable, and the request fails. Disconnect and reconnect mechanism

How to improve the performance of JSON.stringify

Use the second parameter to specify the attribute to be converted, and convert on demand

Tell me about your understanding of the temporary dead zone in JS. What are its application scenarios?

var v=1;
{
    v = 2;
    let v;
}

An error will be reported here: Cannot access 'v' before initialization

What is the function of document.domain? What are its limitations?

    document.domain It can realize cross domain access in some cases.
    Two domain names must belong to the same basic domain name!And the protocols and ports used should be consistent
    (Ports can be set on both pages domain,Reset port to null To achieve cross domain)

Why can axios be called in two ways: object and function? How is it achieved?

start

axios source initialization
The first step to look at the source code is package.json. The main main entry file is generally declared.

// package.json
{
"name": "axios",
"version": "0.19.0",
"description": "Promise based HTTP client for the browser and node.js",
"main": "index.js",
// ...
}


Main entry file

// index.js
module.exports = require('./lib/axios');


4.1 lib/axios.js main file
The axios.js file code is relatively large. It is divided into three parts.

Part I: introduce some tool functions, such as utils, Axios constructor, default configuration, etc.
The second part is to generate instance objects axios, axios.Axios, axios.create, etc.
The third part cancels the relevant API implementation, as well as all, spread, export and other implementations.

4.1.1 part I
Introduce some tool functions, such as utils, Axios constructor, default configuration, etc.
//Part I:
 

// lib/axios


// Strict mode


'use strict';
// There are many tools and methods for introducing utils objects.
var utils = require('./utils');
// Introducing bind method
var bind = require('./helpers/bind');
// Core constructor Axios
var Axios = require('./core/Axios');
// Merge configuration method
var mergeConfig = require('./core/mergeConfig');
// Import default configuration
var defaults = require('./defaults');


4.1.2 Part II
Generate instance objects Axios, axios.Axios, axios.create, etc.
 

/**

Create an instance of Axios

@param {Object} defaultConfig The default config for the instance
@return {Axios} A new instance of Axios
*/
function createInstance(defaultConfig) {
// new an Axios generated instance object
var context = new Axios(defaultConfig);
// bind returns a new wrap function,
// That is why calling Axios calls the Axios.prototype.request function
var instance = bind(Axios.prototype.request, context);
// Copy axios.prototype to instance
// Copy Axios.prototype to the instance.
// That is why there are alias methods such as axios.get,
// Alias methods such as Axios.prototype.get are called.
utils.extend(instance, Axios.prototype, context);
// Copy context to instance
// Copy context to intance instance
// That is why axios.defaults and interceptors can be used by default
// They are actually new Axios().defaults and new Axios().interceptors
utils.extend(instance, context);
// Finally, the instance object is returned. The above code is reflected in the figure above. You can take a closer look at the picture above.
return instance;
}
// Create the default instance to be exported
// Export create default instance
var axios = createInstance(defaults);
// Expose Axios class to allow class inheritance
// Expose Axios class and allow class inheritance, that is, you can new axios.Axios()
// But this is not mentioned in the axios document, and we usually use it less.
axios.Axios = Axios;

// Factory for creating new instances
// Factory mode creates a new instance. Users can customize some parameters
axios.create = function create(instanceConfig) {
return createInstance(mergeConfig(axios.defaults, instanceConfig));
};


Here is a brief description of the factory mode. axios.create, that is, users do not need to know how to implement it internally.
For example, when we buy a mobile phone, we don't need to know how to do it. It's the factory model.
After reading the second part, it involves several tool functions, such as bind and extend. Next, let's talk about these tools and methods.
4.1.3 bind of tools and methods

axios/lib/helpers/bind.js
'use strict';
// Returns a new function wrap
module.exports = function bind(fn, thisArg) {
return function wrap() {
var args = new Array(arguments.length);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
// Put the argument object in the array args
return fn.apply(thisArg, args);
};
};



Pass two arguments to the function and thisArg point.
The parameter arguments generates an array, and finally calls the return parameter structure.
In fact, now apply supports array objects such as arguments, and there is no need to manually convert the array.
So why does the author want to convert arrays for performance? Didn't support it then? Or does the author not know? I don't know. Some readers know that you are welcome to tell the author in the comment area.
For readers who are not very familiar with apply, call and bind, you can see another interviewer's question series.
The interviewer asked: can you simulate the bind ing method of JS
 

for instance
function fn(){
console.log.apply(console, arguments);
}
fn(1,2,3,4,5,6, 'Ruokawa');
// 1 2 3 4 5 6 'Ruochuan'


4.1.4 tools and methods: utils.extend

axios/lib/utils.js
function extend(a, b, thisArg) {
forEach(b, function assignValue(val, key) {
if (thisArg && typeof val === 'function') {
a[key] = bind(val, thisArg);
} else {
a[key] = val;
}
});
return a;
}


In fact, it is to traverse the parameter b object and copy it to the a object. If it is a function, it is called with bind.
4.1.5 tools and methods utils.forEach
 

axios/lib/utils.js
 Traverse arrays and objects. Design patterns are called iterator patterns. Many source codes have traversal functions like this. For example, as we all know jQuery $.each. 
/**

@param {Object|Array} obj The object to iterate
@param {Function} fn The callback to invoke for each item
*/
function forEach(obj, fn) {
// Don't bother if no value provided
// Judge null and undefined and return directly
if (obj === null || typeof obj === 'undefined') {
return;
}
// Force an array if not already something iterable
// If it's not an object, put it in the array.
if (typeof obj !== 'object') {
/eslint no-param-reassign:0/
obj = [obj];
}

// If it is an array, use the for loop to call the fn function. Parameters are similar to the first three parameters of Array.prototype.forEach.
if (isArray(obj)) {
// Iterate over array values
for (var i = 0, l = obj.length; i < l; i++) {
fn.call(null, obj[i], i, obj);
}
} else {
// Iterate over object keys
// Use for in to traverse the object, but for in traverses the traversable properties on the prototype chain.
// So use hasOwnProperty to filter its own properties.
// In fact, Object.keys can also be used to traverse. It does not traverse the traversable attributes on the prototype chain.
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
fn.call(null, obj[key], key, obj);
}
}
}
}


If you are not familiar with Object related APIs, you can view an article written by the author before. JavaScript Object all API parsing
4.1.6 Part III
 

Cancel correlation API Implementation, and all,spread,Export and other implementations.
// Expose Cancel & CancelToken
// Export Cancel and CancelToken
axios.Cancel = require('./cancel/Cancel');
axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel');

// Expose all/spread
// Export all and spread API s
axios.all = function all(promises) {
return Promise.all(promises);
};
axios.spread = require('./helpers/spread');

module.exports = axios;

// Allow use of default import syntax in TypeScript
// That is, it can be introduced in the following ways
// import axios from 'axios';
module.exports.default = axios;


Here we introduce spread. The cancelled API will not be analyzed for the time being, and will be analyzed in detail later.
Suppose you have such a need.

function f(x, y, z) {}
var args = [1, 2, 3];
f.apply(null, args);


Then you can use the spread method. Usage:

axios.spread(function(x, y, z) {})([1, 2, 3]);


The implementation is also relatively simple. Source code implementation:

/**

@param {Function} callback
@returns {Function}
*/
module.exports = function spread(callback) {
return function wrap(arr) {
return callback.apply(null, arr);
};
};


Above var context = new Axios(defaultConfig);, Next, we introduce the core constructor Axios.
4.2 core constructor Axios

axios/lib/core/Axios.js
 Constructor Axios. 
function Axios(instanceConfig) {
// Default parameters
this.defaults = instanceConfig;
// Interceptor request and response interceptor
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}


 

Axios.prototype.request = function(config){
// This is the core method, which will be described in detail with examples later
// code ...
var promise = Promise.resolve(config);
// code ...
return promise;
}
// This is the function to obtain Uri, which is omitted here
Axios.prototype.getUri = function(){}
// Provide aliases for some request methods
// Provide aliases for supported request methods
// Traversal execution
// That is, why can we call axios.get and other aliases, and call the Axios.prototype.request method
// This is also reflected in the axios structure diagram above.
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
/eslint func-names:0/
Axios.prototype[method] = function(url, config) {
return this.request(utils.merge(config || {}, {
method: method,
url: url
}));
};
});

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
/eslint func-names:0/
Axios.prototype[method] = function(url, data, config) {
return this.request(utils.merge(config || {}, {
method: method,
url: url,
data: data
}));
};
});

module.exports = Axios;


Next, look at the interceptor section.
4.3 interceptor Manager

Pre request interception, and post request interception.
stay Axios.prototype.request Function, how to realize the interception, which will be described in detail with examples later.
axios github Warehouse interceptor document
 How to use:
// Add a request interceptor
// Add pre request interceptor
axios.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});

// Add a response interceptor
// Add post request interceptor
axios.interceptors.response.use(function (response) {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response;
}, function (error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
return Promise.reject(error);
});

If you want to put the interceptor, you can use it eject method.
const myInterceptor = axios.interceptors.request.use(function () {/.../});
axios.interceptors.request.eject(myInterceptor);


Interceptors can also be added to custom instances.

const instance = axios.create();
instance.interceptors.request.use(function () {/.../});



Source code implementation:
Constructor and handles are used to store interceptor functions.

function InterceptorManager() {
this.handlers = [];
}



Next, three methods are declared: use, remove and traverse.
4.3.1 use of interceptormanager.prototype.use
Pass two functions as parameters. One item in the array stores {fully: function() {} and rejected: function() {}. Returns the numeric ID used to remove the interceptor.

 

/**

@param {Function} fulfilled The function to handle then for a Promise
@param {Function} rejected The function to handle reject for a Promise

@return {Number} return ID To use eject remove
/
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected
});
return this.handlers.length - 1;
};


4.3.2 InterceptorManager.prototype.eject removal
Remove the interceptor according to the ID returned by use.
 

/*

@param {Number} id The ID that was returned by use
/
InterceptorManager.prototype.eject = function eject(id) {
if (this.handlers[id]) {
this.handlers[id] = null;
}
};
Copy code
 It is somewhat similar to timers setTimeout and setInterval. The return value is id. Clear the timer with clearTimeout and clearInterval.
// Mention that the timer callback function can pass parameters, and the return value timer is a number
var timer = setInterval((name) => {
console.log(name);
}, 1000, 'Ruokawa ');
console.log(timer); // Digital ID
// Enter this sentence in the console and the timer will be cleared
clearInterval(timer);
Copy code
4.3.3 InterceptorManager.prototype.forEach ergodic
 Traverse and execute all interceptors, pass a callback function (each interceptor function is used as a parameter) call, and the removed item is null, so it will not be executed, which achieves the effect of removal.
/*
@param {Function} fn The function to call for each interceptor
*/
InterceptorManager.prototype.forEach = function forEach(fn) {
utils.forEach(this.handlers, function forEachHandler(h) {
if (h !== null) {
fn(h);
}
});
};


 

  1. Example combination
    The npm start run during debugging described above uses the file in the path of axios/sandbox/client.html as an example. Readers can debug by themselves.
    The following is a section of the code in this file.
axios(options)
.then(function (res) {
response.innerHTML = JSON.stringify(res.data, null, 2);
})
.catch(function (res) {
response.innerHTML = JSON.stringify(res.data, null, 2);
});

end

How to hide JavaScript code in browsers that do not support js?

stay<script>Add to the code after the tag“<!-– ",Without quotation marks.
stay</script>Add before label“// - > ", no quotation marks in the code.
The old browser will now JavaScript The code is treated as a long one HTML Comments are not supported JavaScript Your browser will“<! – "And“// - > "as a line comment.
For example:
<script><!--
alert();
// --></script>

What is the JSSDK of wechat and how to access it?

WeChat JS-SDK: Is the developer on the web through JavaScript The code uses the toolkit of wechat's native functions. Developers can use it to record and play wechat voice on Web pages, monitor wechat sharing, upload local pictures of mobile phones, take photos and many other capabilities.

JSSDK Use steps
 Step 1: bind domain name
 Step 2: Import JS file
 Step 3: Pass config Interface injection permission verification configuration
 Step 4: Pass ready Interface processing successful verification
 Step 5: Pass error Interface processing failed validation


To be continued

Posted by shlomikalfa on Tue, 28 Sep 2021 18:22:39 -0700