Js determines whether two JSON files are the same

You need to determine the data types in JSON and unpack the nesting of objects.

        function isEqual() {
            var arg = getArg(arguments);
            var o1 = arg["object"] [0] | | []; var o2 = arg["object"] [1] | | [];if(! arg["object"].length) {
                return (o1 == o2);
            }
            var isEqualForInner = function (obj1, obj2) {
                var o1 = obj1 instanceof Object;
                var o2 = obj2 instanceof Object;
                if(! o1 || ! o2) {return obj1 === obj2;
                }
                if(Object.keys(obj1).length ! == Object.keys(obj2).length) {return false;
                }
                for (var attr in obj1) {
                    var t1 = obj1[attr] instanceof Object;
                    var t2 = obj2[attr] instanceof Object;
                    if (t1 && t2) {
                        return isEqualForInner(obj1[attr], obj2[attr]);
                    } else if(obj1[attr] ! == obj2[attr]) {return false; }}return true;
            }
            function getArg(arg) {
                var ret = {
                    'number': [].'string': [].'boolean': [].'object': [].'Object': [].'Array': [].'function': [].'Date': [].'null': []}for (var i = 0, len = arg.length; i < len; i++) {
                    var ar = arg[i];
                    if (typeof (ar) == 'number') {
                        ret['number'].push(ar);
                    } else if (typeof (ar) == 'string') {
                        ret['string'].push(ar);
                    } else if (typeof (ar) == 'boolean') {
                        ret['boolean'].push(ar);
                    } else if (typeof (ar) == 'function') {
                        ret['function'].push(ar);
                    } else if (typeof (ar) == 'object') {
                        if (ar) {
                            if (ar.constructor == Object) {
                                ret['object'].push(ar);
                                ret['Object'].push(ar);
                            } else if (ar.constructor == Array) {
                                ret['object'].push(ar);
                                ret['Array'].push(ar);
                            } else if (ar.constructor == Date) {
                                ret['Date'].push(ar); }}else {
                            ret['null'].push(ar); }}}return ret;
            }
            return isEqualForInner(o1, o2);
        }
Copy the code

To realize the bind

The bind() method creates a new function, and when bind() is called, this of the new function is specified as the first argument to bind(), and the remaining arguments will be used as arguments to the new function.

        Function.prototype.my_bind = function() {var self = this, / / save the original context = Array. The prototype. The shift. The call (the arguments), // The previous line is equivalent to context = [].shift.call(arguments); args = Array.prototype.slice.call(arguments); // The remaining parameters are converted to arraysreturn functionA new function () {/ / return the self. The apply (context, Array. Prototype. Concat. Call (args, Array. Prototype. Slice. The call (the arguments))); }}Copy the code

To realize the call

/ / ideas: on this is going to change this point method on target to execute and return Function. The prototype. Mycall =function (context) {
  if(typeof this ! = ='function') {
    throw new TypeError('not funciton')
  }
  context = context || window
  context.fn = this
  let arg = [...arguments].slice(1)
  letresult = context.fn(... arg) delete context.fnreturn result
}
Copy the code

To realize the apply

/ / ideas: on this is going to change this point method on target to execute and return Function. The prototype. Myapply =function (context) {
  if(typeof this ! = ='function') {
    throw new TypeError('not funciton')
  }
  context = context || window
  context.fn = this
  let result
  if(arguments[1]) { result = context.fn(... arguments[1]) }else {
    result = context.fn()
  }
  delete context.fn
  return result
}
Copy the code

Implement new methods

/* * 1. Create an empty object * 2. Link to prototype * 3. Bind this value * 4. Return a new object */ // first implementationfunction createNew() {
    letObj = {} // 1. Create an empty objectlet constructor = [].shift.call(arguments)  
    // let[constructor,...args] = [...arguments] obj.__proto__ = constructor.prototype // 2. Link to the prototypeletresult = constructor.apply(obj, arguments) // 3. Bind this value //let result = constructor.apply(obj, args)   

    return typeof result === 'object'? Result: obj // 4.function People(name,age) {
    this.name = name
    this.age = age
}

let peo = createNew(People,'Bob',22)
console.log(peo.name)
console.log(peo.age)
Copy the code

Shallow copy, deep copy implementation

Shallow copy

/ / 1.... implementationletcopy1 = {... {x:1}} // 2. object. assign implementationlet copy2 = Object.assign({}, {x:1})
Copy the code

Deep copy

Josn.stringify ()/ json.parse ()/ / Disadvantages: Copying objects containing regular expressions, functions, or undefined equivalents will failletobj = {a: 1, b: {x: 3}} JSON.parse(JSON.stringify(obj)) // 2. A recursive copyfunction deepClone(obj) {
  let copy = obj instanceof Array ? [] : {}
  for (let i in obj) {
    if (obj.hasOwnProperty(i)) {
      copy[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
    }
  }
  return copy
}
Copy the code

Implement instanceof

// The prototype of the right variable exists in the prototype chain of the left variablefunction instanceOf(left, right) {
  let leftValue = left.__proto__
  let rightValue = right.prototype
  while (true) {
    if (leftValue === null) {
      return false
    }
    if (leftValue === rightValue) {
      return true
    }
    leftValue = leftValue.__proto__
  }
}
Copy the code

The function is currified

Definition of a Currization function: To convert a multi-parameter function into a single-parameter form. The principle behind the implementation of a Currization function is to use the closure principle to form a non-destructible scope during execution, then store the pre-processed content in this non-destructible scope, and return a function with the least arguments.

The first is to fix the passed parameters and execute them when enough parameters are passed

/** * Implementation note: When a function receives enough arguments, it executes the original function, so how do we determine when enough arguments are reached? * The currization function needs to remember the arguments you gave it, if not, it defaults to an empty array. * On each subsequent call, we need to check that the arguments are sufficient, and if so, we will execute fn, and if not, we will return a new curry function, stuffing it with the existing arguments. * */ // The function to be currifiedlet sum = (a, b, c, d) => {
  returnA + b + c + d} // Return a processed functionletcurry = (fn, ... Arr) => {// ARR records existing parametersreturn(... Args) => {// ARgs receives new parametersif(fn.length <= (... arr,... Args)) {// If the argument is sufficient, the execution is triggeredreturnfn(... arr, ... args) }else{// Continue adding parametersreturn curry(fn, [...arr, ...args])
    }
  }
}

var sumPlus = curry(sum)
sumPlus(1)(2)(3)(4)
sumPlus(1, 2)(3)(4)
sumPlus(1, 2, 3)(4)
Copy the code

The second way: do not fix the incoming parameter, execute at any time

/** * The main function of the Currization is to delay execution. The execution condition is not necessarily equal to the number of arguments, but can also be other conditions. * For example, if the parameter is 0, then we need to modify the above function slightly */ // to be curriedlet sum = arr => {
  return arr.reduce((a, b) => {
    return a + b
  })
}

letcurry = (fn, ... Arr) => {// ARR records existing parametersreturn(... Args) => {// ARgs receives new parametersif(args. Length === 0) {// If the parameter is empty, execution is triggeredreturnfn(... arr, ... args) }else{// Continue adding parametersreturncurry(fn, ... arr, ... args) } } } var sumPlus = curry(sum) sumPlus(1)(2)(3)(4)() sumPlus(1, 2)(3)(4)() sumPlus(1, 2, 3)(4)()Copy the code

ES6 writing

const curry = (fn, arr = []) => (... args) => ( arg => arg.length === fn.length ? fn(... arg) : curry(fn, arg) )([...arr, ...args])letCurryTest = curry ((a, b, c, d) = > a + b + c + d) curryTest (1, 2, 3) (4) / / return 10 curryTest (1, 2) and (4) and (3) / / return 10 curryTest (1, 2) (3, 4) / / return 10Copy the code

To implement the Event bus

Class EventEmitter {class EventEmitter {constructor() {/ / storage events this. Events = this. Events | | new Map ()} / / listen for an event addListener (type, fn) {
    if(! this.events.get(type)) {
      this.events.set(type, fn)}} //type) {
    let handle = this.events.get(type) handle. Apply (this, the arguments [...]. Slice (1))}} / / testletEmitter = new EventEmitter()'ages', age => {console.log(age)})'ages'/ / 18, 18)Copy the code

Implement a two-way data binding

let obj = {}
let input = document.getElementById('input')
let span = document.getElementById('span'DefineProperty (obj,'text', {
  configurable: true,
  enumerable: true.get() {
    console.log('Got the data')},set(newVal) {
    console.log('Data updated'InnerHTML = newVal}}) input.value = newVal sp.innerhtml = newVal}})'keyup'.function(e) {
  obj.text = e.target.value
})
Copy the code

Realize the Promise

// No other boundary cases such as asynchronous processing are added // ① automatic execution function, ② three states, ③thenClass Promise {constructor (fn) {// This. State ='pending'
    this.value = undefined
    this.reason = undefined
    let resolve = value => {
      if (this.state === 'pending') {
        this.state = 'fulfilled'
        this.value = value
      }
    }
    let reject = value => {
      if (this.state === 'pending') {
        this.state = 'rejected'This. Reason = value}} // Try {fn(resolve, reject)} catch (e) {reject(e)}} //then
  then(onFulfilled, onRejected) {
    switch (this.state) {
      case 'fulfilled':
        onFulfilled(this.value)
        break
      case 'rejected':
        onRejected(this.value)
        break
      default:
    }
  }
}
Copy the code

Implement a simple route

// hashRouting is a class Route {constructor(){this.routes = {} // currenthash
    this.currentHash = ' 'FreshRoute = this.freshroute. bind(this) // Listen for window.adDeventListener ('load', this.freshRoute, false)
    window.addEventListener('hashchange', this.freshRoute, false} / / storage storeRoute (path, cb) {enclosing routes/path = cb | |function() {}} // UpdatefreshRoute () {
    this.currentHash = location.hash.slice(1) || '/'
    this.routes[this.currentHash]()
  }
}
Copy the code

Implementing lazy loading

<ul>
  <li><img src="./imgs/default.png" data="./imgs/1.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/2.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/3.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/4.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/5.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/6.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/7.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/8.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/9.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/10.png" alt=""></li>
</ul>
Copy the code
let imgs =  document.querySelectorAll('img') // Viewable heightlet clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
function lazyLoad() {// Roll off the heightlet scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
  for (leti = 0; i < imgs.length; I ++) {// The height of the image in the viewable arealetX = clientHeight + scrollTop - imgs[I]if (x > 0 && x < clientHeight+imgs[i].height) {
      imgs[i].src = imgs[i].getAttribute('data')
    }
  }
}
// addEventListener('scroll', lazyLoad) or setInterval(lazyLoad, 1000)
Copy the code

With regular and non-regular, to achieve a string to hump

irregular

let str = "get-element-by-id";
    function fun1(str) {
      var strArr = str.split("-");
      for (var i = 1; i < strArr.length; i++) {
        var start = strArr[i].charAt(0).toUpperCase();
        var end = strArr[i].slice(1);
        strArr[i] = start + end;
      }
      return strArr.join("");
    }
    console.log(fun1(str));
Copy the code

Regular 1

 let str = "get-element-by-id";
    functionThe fun1(STR) {//\w metacharacter is used to match word characters, which is equivalent to"[a-zA-Z0-9]". var reg = /-(\w)/g; // Subitems () represent subitemsreturn str.replace(reg, function($0.The $1{/ /$0If the replace () method has multiple arguments, the first argument is the result of the match, and the second argument is the first child of console.log().$0); //-b
        console.log(The $1); //b
        return The $1.toUpperCase();
      });
    }
    console.log(fun1(str));
Copy the code

Regular 2

let str = "get-element-by-id";
    var reg = /-\w/g;
    functionThe fun1(STR) {//\w metacharacter is used to match word characters, which is equivalent to"[a-zA-Z0-9]".return str.replace(reg, function($) {
        //console.log($); //-e -b -i
        return $.slice(1).toUpperCase();
      });
    }
    console.log(fun1(str));
Copy the code

Determine the most frequent occurrences of a character in a string and count the number of occurrences

var str = "asdfssaaasasasasaa";
    var obj = {};
    for (var i = 0; i < str.length; i++) {
      if(! obj[str.charAt(i)]) { obj[str.charAt(i)] = 1; }else {
        obj[str.charAt(i)]++;
      }
    }
    var count = 0;
    var word = "";
    for (var i in obj) {
      if (obj[i] > count) {
        count = obj[i];
        word = i;
      }
    }
    console.log("Most frequently :" + word + "A" + count + "Time");
Copy the code

Implement function throttling

For continuous events, specify an interval (n seconds) that can only be executed once in a certain interval.

function _throttle(fn, time) { 
 
  let _self = fn, 
      timer,  
      firstTime = true// Record whether the flag is executed for the first timereturn function() { 
    letArgs = arguments, // Solve closure argument problem _me = this // solve context loss problemif(firstTime) {// if it is the firstTime, just execute _self.apply(_me, args)return firstTime = false
    }
    if(timer) {// If the timer exists, an event listener is runningreturn false
    }
 
    timer = setTimeout(function() { 
      clearTimeout(timer)
      timer = null
      _self.apply(_me, args)
    }, time || 500)
  }
}
 
function _log(){
    console.log(1)
}
window.onscroll = _throttle(_log,500)
Copy the code

Function stabilization

The action is executed after n milliseconds. If the action is invoked within n milliseconds, the execution time is recalculated

function _debounce(fn,wait,time){ var previous = null; Var timer = null;return function(){
        var now = +new Date();
 
        if(! previous) previous = now; // If the difference between the last execution time and the current execution time is greater than the set execution interval, the active executionif(now - previous > time){ clearTimeout(timer); fn(); previous = now; // Immediately after executing the function, record the current time}else{
            clearTimeout(timer);
            timer = setTimeout(function(){
                fn();
            },wait); }}}function _log(){console.log(1)} window.onscroll = _debounce(_log,500,2000)Copy the code

Calculates the difference between two arrays

function difference(arr1, arr2) {
        var res = [];
        for (var i = 0, len = arr1.length; i < len; i++) {
            if(arr2.indexOf(arr1[i]) === -1) { res.push(arr1[i]); }}for (var j = 0, len = arr2.length; j < len; j++) {
            if(arr1.indexOf(arr2[j]) === -1) { res.push(arr2[j]); }}return res;
    }
Copy the code