Top JavaScript Coding Interview Questions and Answers in 2023

    The most complete in history! 56 JavaScript advanced handwriting knowledge points! Help you from beginner to advanced JavaScript player

    The most common test in the interview

    1.Simulate the new operation

    function myNew(ctor, ...args) {
         const obj = Object.create(ctor.prototype); //Create an object and point to the constructor prototype
         //Equivalent to
         // const obj = new Object()
         // obj.__proto__ = ctor.prototype;
         const res = ctor.apply(obj, args); //Point the this of ctor to the newly created object
         return typeof res === 'object' ? res : obj;
         //If the constructor does not return data of the object type, the result of new is the object created in step 1.
       }
    


    2.instanceof keyword

    function myInstanceof(left, right) {
             if (typeof left !== 'object' || left === null) return false;
             let proto = left.__proto__;
             let prototype = right.prototype;
             while (true) {
               if (!proto) return false
    // 3. The end of the prototype chain is null until it is not found at the end, then return false
               if (proto === prototype) return true
    //1. If the left and right prototypes are the same, it means that the prototype of the constructor on the right is on the prototype chain of the instance object on the left
               proto = proto.__proto__
    // 2. If the comparison is not successful, then continue to find the prototype on the left
             }
           }
    


    3.Realize debounce function

    function myDebounce(fn, delay, immediate = false) {
         let timer = null;
         let isimmediate = false;
         const _debounce = function () {
           if (timer) clearTimeout(timer);
           // Determine whether to execute immediately
           if (immediate && !isimmediate) {
             fn.apply(this, arguments);
             isimmediate = true;
           } else {
             //Pay attention to the arrow function, otherwise this points to window
             timer = setTimeout(() => {
               fn.apply(this, arguments);
               // Let the next time you re-enter, you can decide whether to execute immediately according to immediate
               isimmediate = false;
             }, delay);
           }
         };
         return_debounce;
       }
    


    4.Realize throttling function

    function throttle(fn, delay){
        let  flag =true
        const _throttle = function(){
            if(!flag) return
            flag = false
            setTimeout(()=>{
                fn.apply(this, arguments)
                flag = true
            },delay)
        }
        return _throttle
    }
    


    5.Implement native AJAX requests

    const ajax = {
        get(url, fn) {
            const xhr = new XMLHttpRequest()
            xhr.open('GET', url, true)
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    fn(xhr.responeText)
                }
            }
            xhr.send()
        },
        post(url, data, fn) {
            const xhr = new XMLHttpRequest()
            xhr.open('POST', url, true)
            xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded')
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    fn(xhr.responeText)
                }
            }
            xhr.send(data)
        }
    }
    


    6.Implement an LRU cache function

    class LRUCache {
      constructor(size) {
        this.size = size
        this.cache = new Map()
      }
    
      get(key) {
        const hasKey = this.cache.has(key)
        if (hasKey) {
          const val = this.cache.get(key)
          this.cache.delete(key)
          this.cache.set(key, val)
          return val
        } else {
          return -1
        }
      }
    
      put(key, val) {
        const hasKey = this.cache.has(key)
        if (hasKey) {
          this.cache.delete(key)
        }
        this.cache.set(key, val)
        if (this.cache.size > this.size) {
          this.cache.delete(this.cache.keys().next().value)
        }
      }
    
    }
    


    7.Simple implementation of publish and subscribe mode

    // Handwritten publish and subscribe mode EventEmitter
           class EventEmitter {
             constructor() {
               this.events = {};
             }
             // implement subscription
             on(type, callBack) {
               if (!this.events) this.events = Object.create(null);
               if (!this. events[type]) {
                 this.events[type] = [callBack];
               } else {
                 this.events[type].push(callBack);
               }
             }
             // delete subscription
             off(type, callBack) {
               if (!this.events[type]) return;
               this.events[type] = this.events[type].filter((item) => {
                 return item !== callBack;
               });
             }
             // Subscribe to the event only once
             once(type, callBack) {
               function fn() {
                 callBack();
                 this.off(type, fn);
               }
               this.on(type, fn);
             }
             // trigger event
             emit(type, ... rest) {
               this.events[type] &&
                 this.events[type].forEach((fn) => fn.apply(this, rest));
             }
           }
           // Use as follows
           const event = new EventEmitter();
           const handle = (...rest) => {
             console. log(rest);
           };
           event.on("click", handle);
           event. emit("click", 1, 2, 3, 4);
           event.off("click", handle);
           event. emit("click", 1, 2);
           event.once("dbClick", () => {
             console.log(123456);
           });
           event. emit("dbClick");
           event. emit("dbClick");
    


    8.Convert DOM into a tree-structured object

    <div>
         <span></span>
         <ul>
             <li></li>
             <li></li>
         </ul>
    </div>
    
    Convert the upper DOM into the lower tree structure object
    
    {
         tag: 'DIV',
         children: [
             { tag: 'SPAN', children: [] },
             {
                 tag: 'UL',
                 children: [
                     { tag: 'LI', children: [] },
                     { tag: 'LI', children: [] }
                 ]
             }
         ]
    }
    

    Code:

    function dom2tree(dom) {
        const obj = {}
        obj.tag = dom.tagName
        obj.children = []
        dom.childNodes.forEach(child => obj.children.push(dom2tree(child)))
        return obj
    }
    


    9.Convert tree structure to DOM

    // real rendering function
    function _render(vnode) {
       // If it is a numeric type, convert it to a string
       if (typeof vnode === "number") {
         vnode = String(vnode);
       }
       // The string type is directly a text node
       if (typeof vnode === "string") {
         return document.createTextNode(vnode);
       }
       // normal DOM
       const dom = document.createElement(vnode.tag);
       if (vnode.attrs) {
         // traverse properties
         Object.keys(vnode.attrs).forEach((key) => {
           const value = vnode.attrs[key];
           dom.setAttribute(key, value);
         });
       }
       // recursive operation on subarrays
       vnode.children.forEach((child) => dom.appendChild(_render(child)));
       return dom;
    }
    


    10.Calculate the number of layers of an object

    const obj = {
        a: { b: [1] },
        c: { d: { e: { f: 1 } } }
    }
    
    console.log(loopGetLevel(obj)) // 4
    

    Code:

    function loopGetLevel(obj) {
        var res = 1;
    
        function computedLevel(obj, level) {
            var level = level ? level : 0;
            if (typeof obj === 'object') {
                for (var key in obj) {
                    if (typeof obj[key] === 'object') {
                        computedLevel(obj[key], level + 1);
                    } else {
                        res = level + 1 > res ? level + 1 : res;
                    }
                }
            } else {
                res = level > res ? level : res;
            }
        }
        computedLevel(obj)
    
        return res
    }
    


    11.flattening of objects

    /*
       raw data
    const obj = {a: 1,b: [1, 2, { c: true }],c: { e: 2, f: 3 },g: null,};
    transform into
    {a: 1,'b[0]': 1,'b[1]': 2,'b[2].c': true,'c.e': 2,'c.f': 3, g: null}
    */
     function objFlat(obj) {
            let res = {};
            let foo = (key, value) => {
              if (Array.isArray(value)) {
                for (let i = 0; i < value.length; i++) {
                  foo(`${key}[${i}]`, value[i]);
                }
                if (value.length === 0) res[key] = [];
              } else if (value instanceof Object) {
                let keys = Object.keys(value);
                for (let i of keys) {
                  foo(`${key}.${i}`, value[i]);
                }
                if (keys.length === 0) res[key] = {};
              } else {
                res[key] = value;
              }
            };
            Object.keys(obj).forEach((v) => foo(v, obj[v]));
            return res;
          }
    


    12.Implement deep copy

      function deepClone(obj) {
        if (typeof obj !== 'object' || obj === null) return obj;
         if (obj instanceof RegExp) {
          return new RegExp(obj);
        }
        let res = obj instanceof Array ? [] : {};
        for (let key in obj) {
          res[key] =
            typeof obj[key] == 'object' ? deepClone(obj[key]) : obj[key];
        }
        return res;
      }
    


    13.Handwritten Inheritance

    Detailed Explanation of Prototype Chain and Handwritten Inheritance


    14.handwritten quicksort

    function quick(ary) {
       // 4. End the recursion (if there is less than or equal to one item in ARY, it will not be processed)
       if (ary. length <= 1) {
         return ary;
       }
       // 1. Find the middle item of the array and remove it from the original array
       let middleIndex = Math. floor(ary. length / 2);
       let middleValue = ary.splice(middleIndex, 1)[0];
       // 2. Prepare two left and right arrays, loop through each item in the remaining array, put the item smaller than the current item in the left array, otherwise put it in the right array
       let aryLeft = [],
         aryRight = [];
       for (let i = 0; i < ary. length; i++) {
         let item = ary[i];
         item < middleValue ? aryLeft.push(item) : aryRight.push(item);
       }
       // 3. The recursive method allows the left and right arrays to continue to be processed in this way until the left and right sides are sorted (finally let the left + middle + right stitching become the final result)
       return quick(aryLeft).concat(middleValue, quick(aryRight));
    }
    


    15.Implement thousands separator

      function _comma(number) {
        if(number<0) {
            return '-'+foo(-number)
        }else{
            return foo(number)
        }
    
        function foo(number) {
          if (number < 1000) {
            return number.toString();
          } else {
            return (
              foo(Math.floor(number / 1000)) + ',' + foo(number % 1000)
            );
          }
        }
    }
    


    16.Extract url parameters

      const _getParams = (url) => {
        const querys = {};
        const params =
          url.indexOf('?') !== -1 ? url.split('?')[1].split('&') : [];
        console.log(params);
        params.forEach((item) => {
          let arr = item.split('=');
          querys[arr[0]] = arr[1];
        });
    
        return querys;
      };
    


    17.Please use prototype chain or class to implement chained addition, subtraction, multiplication and division
    use prototype chain:

      function myCalculator(num) {
        this.num = num;
      }
      myCalculator.prototype.add = function (value) {
        this.num += value;
        return this;
      };
      myCalculator.prototype.minus = function (n) {
        this.num = this.num - n;
        return this;
      };
      myCalculator.prototype.multi = function (n) {
        this.num = this.num * n;
        return this;
      };
      myCalculator.prototype.div = function (n) {
        this.num = this.num / n;
        return this;
      };
      myCalculator.prototype.pow = function (n) {
        this.num = this.num ** n;
        return this;
      };
      let sum = new myCalculator(123);
      sum.add(1).minus(4);
      console.log(sum.num);//120
    

    use Class:

    class myCalculator {
        constructor(value) {
          this.value = value;
        }
        add(newValue) {
          this.value = this.value + newValue;
          return this;
        }
        reduction(newValue) {
          this.value = this.value - newValue;
          return this;
        }
        take(newValue) {
          this.value = this.value * newValue;
          return this;
        }
        division(newValue) {
          this.value = this.value / newValue;
          return this;
        }
        pow(num) {
          this.value = this.value ** num;
          return this;
        }
      }
    
      let num = new myCalculator(1);
      let afterDate = num.add(2).reduction(2).take(5).division(2);
      console.log(afterDate.value);//2.5
    


    18.CamelCase conversion

         /**
            {
                user_info: {
                  user_address: {
                    user_province: 'Zhe Jiang',
                  },
                  user_name: 'Joe Zhang',
                },
                favorite_food: [
                  {
                    food_name: 'curry',
                    sense_of_taste: 'spicy',
                  },
                  {
                    food_name: 'orange',
                    food_type: 'sweet',
                  },
                ],
              }
    
    
              {
                userInfo: {
                  userAddress: {
                    userProvince: 'Zhe jiang',
                  },
                  userName: 'Joe Zhang'
                },
               favoriteFood: [
                  {
                   foodName: 'curry',
                    senseOfTaste: 'spicy'
                  },
                  {
                    foodName: 'orange',
                    foodType: 'sweet'
                  }
                ]
              }
    
             **/
    

    Underscore to camelCase:

    const mapSnakeToCamel = (data) => {
         if (typeof data != 'object' || !data) return data;
         if (Array.isArray(data)) {
           return data. map((item) => mapSnakeToCamel(item));
         }
    
         const newData = {};
         for (let key in data) {
           let newKey = key.replace(/_([a-z])/g, (p, m) => {
          //p is all the characters matched, m is the character matched by the first parenthesis, because _ is not in the parentheses, so there is no match
             return m.toUpperCase();
           });
           newData[newKey] = mapSnakeToCamel(data[key]);
         }
         return newData;
       };
    

    CamelCase to underscore:

      function underline(data) {
        if (typeof data != 'object' || !data) return data;9
        if (Array.isArray(data)) {
          return data.map((item) => underline(item));
        }
    
        const newData = {};
        for (let key in data) {
          let newKey = key.replace(/([A-Z])/g, (p, m) => `_${m.toLowerCase()}`);
          newData[newKey] = underline(data[key]);
        }
        return newData;
      }
    


    19.Cyclic printing of red, yellow and green lights

        /* The red light turns on once in 3s, the green light turns on once in 1s, and the yellow light turns on once in 2s; how to keep the three lights on alternately and repeatedly
        */
     function red() {
        console.log('red');
      }
      function green() {
        console.log('green');
      }
      function yellow() {
        console.log('yellow');
      }
    
      const task = (timer, light) =>
        new Promise((resolve, reject) => {
          setTimeout(() => {
            if (light === 'red') {
              red();
            } else if (light === 'green') {
              green();
            } else if (light === 'yellow') {
              yellow();
            }
            resolve();
          }, timer);
        });
      const taskRunner = async () => {
        await task(3000, 'red');
        await task(2000, 'green');
        await task(2100, 'yellow');
        taskRunner();
      };
      taskRunner();
    


    Array related

    Summary and handwriting of the most complete array method


    Object related

    Define a test object

    const obj = {
     name: 'fryao',
     age: 18,
     gender: 'female'
    }
    

    1. Object.entries

    //Convert an object into an array of key-value pairs
    Object.prototype.myEntries = function (obj) {
        const res = []
        for (let key in obj) {
            obj.hasOwnProperty(key) && res.push([key, obj[key]])
        }
        return res
    }
    
    console.log(Object.myEntries(obj))
    // [ [ 'name', 'fryao' ], [ 'age', 18 ], [ 'gender', 'female' ] ]
    


    2. Object.fromEntries

    //Convert an array of key-value pairs into an object
    Object.prototype.myFromEntries = function (arr) {
        const obj = {}
        for (let i = 0; i < arr.length; i++) {
            const [key, value] = arr[i]
            obj[key] = value
        }
        return obj
    }
    


    3. Object.is

    //Object.is(a, b), determine whether a is equal to b
    Object.prototype.myIs = function (x, y) {
    if (x === y) {
         //When running to 1/x === 1/y, both x and y are 0, but 1/+0 = +Infinity, 1/-0 = -Infinity, are different
         return x !== 0 || y !== 0 || 1 / x === 1 / y
     } else {
     //NaN===NaN is false, this is wrong, we do an intercept here, x !== x, then it must be NaN, y is the same
     //Return true when both are NaN
         return x !== x && y !== y
     }
    }
    


    4. Object.assign
    difficulty

    • assign receives multiple objects and synthesizes multiple objects into one object
    • If these objects have attributes with the same name, the later object attribute values shall prevail
    • assign returns an object, this object === the first object

      //The Object.assign() method is used to copy the values of all enumerable properties from one or more source objects to a target object. It will return the target object.
      
      Object.prototype.sx_assign = function (target, ...args) {
      if (target === null || target === undefined) {
          throw new TypeError('Cannot convert undefined or null to object')
      }
      target = Object(target)
      
      for (let nextObj of args) {
          for (let key in nextObj) {
              nextObj.hasOwnProperty(key) && (target[key] = nextObj[key])
          }
      }
      return target
      }
      


    Function related

    1. Function.apply

    Function.prototype.myApply = function (context, thisArg) {
           if (typeof this !== 'function') {
             throw new TypeError('not a function call');
           }
    
           const fn = Symbol('fn');
           context = context || (typeof window === 'undefined' ? global : window);
           thisArg = thisArg || []; //Fix the second parameter is empty
           context[fn] = this;
           const res = context[fn](...thisArg);
           delete context[fn];
    //Because there is an additional attribute for the object, it needs to be deleted. The call that comes with the system is implemented in C++ and there will be no additional attribute {fn:f}
           return res;
         };
    


    2. Function.call

      Function.prototype.myCall = function (context, ...args) {
        if (typeof this !== 'function') {
          throw new TypeError('Type Error');
        }
        const fn = Symbol('fn');
        context = context?Object(context):window ;
        context[fn] = this;
        const res = context[fn](...args);
        delete context[fn];
        return res;
      };
    


    3. Function.bind

    Function.prototype.myBind = function (thisArg, ...args) {
         var self = this;
         thisArg = thisArg || window;
         return function F() {
           //Because it returns a function, we can new F(), we need to judge whether it can be used as a constructor
           if (this instanceof F) {
             //this instanceof F is true, that is, this = new F(), the priority of new is higher than bind, so there is no need to call to change the direction of this
             return new self(...args, ...arguments);
           }
           return self. call(thisArg, ...args, ...arguments);
     //Combine the two parameters passed in
         };
       };
    


    String related

    1. slice

    String.prototype.mySlice = function (start = 0, end) {
        start = start < 0 ? this.length + start : start
        end = !end && end !== 0 ? this.length : end
    
        if (start >= end) return ''
        let str = ''
        for (let i = start; i < end; i++) {
            str += this[i]
        }
        return str
    }
    


    2. substr

    String.prototype.mySubstr = function (start = 0, length) {
        if (length < 0) return ''
    
        start = start < 0 ? this.length + start : start
        length = (!length && length !== 0) || length > this.length - start ? this.length : start + length   
        let str = ''
        for (let i = start; i < length; i++) {
            str += this[i]
        }
        return str
    }
    


    3. substring

    The function is roughly the same as slice, difference:
    start > end: swap values

    String.prototype.mySubstring = function (start = 0, end) {
        start = start < 0 ? this.length + start : start
        end = !end && end !== 0 ? this.length : end 
        if (start >= end) [start, end] = [end, start]
        let str = ''
        for (let i = start; i < end; i++) {
            str += this[i]
        }   
        return str
    }
    

    Popular posts from this blog

    大学资料分享——广工计院各个科目实验报告、课设及期末复习资料!!

    Win10 远程计算机或设备将不接受连接

    JAVA Traffic Signal Light Course Design (Source Code + Report + Video Demonstration)

    Implementation of Ajax Interceptor