handwrittenPromise

pending

Closure implementationonce

function once(fn) {
  let done = false;
  return function () {
    if(! done) { done =true;
      fn.apply(this.arguments); }}; }const pay = once(function (money) {
  console.log(` selections:${money}`);
});
pay(100);
pay(100);
Copy the code

Throttling function

Only one function is allowed to be executed within the interval; Such functions are function throttles;

Solution a:

function throttle(func ,delay = 500) {
  let timer = null;
  return function () {
    let context = this
    if(! timer){ timer =setTimeout(() = > {
        func.apply(context, arguments)
        timer = null
      }, delay)
    }
  }
}
Copy the code

Scheme 2:

function throttle(func ,delay = 500) {
  let activeTime = 0;
  return function () {
    let context = this
    let current = Date.now();
    if(current - activeTime > delay) {
      func.apply(context, arguments)
      activeTime = Date.now(); }}}Copy the code

Image stabilization function

If a program is executed repeatedly within a certain time interval, the program execution time is reset.

function debounce(fn, delay = 500) {
  let timer = null;
  return function () {
    let context = this
    clearTimeout(timer)
    timer = setTimeout(() = > {
      fn.apply(context, arguments) }, delay); }}Copy the code

implementationmap

const map = (array, fn) = > {
  let results = []
  for (let item of array) {
    results.push(fn(item))
  }
  return results
}
Copy the code

implementationevery

const every = (array, fn) = > {
  let result = true
  for (let value of array) {
    result = fn(value)
    if(! result) {break}}return result
}
Copy the code

implementationsome

const some = (array, fn) = > {
  let result = false
  for (let value of array) {
    result = fn(value)
    if (result) {
      break}}return result
}
Copy the code

Simulation of the lodashmemoizeMethod implementation

function memoize (fn) {
  let cache = {} // Parameter as key, result as value
  return function () {
    let key = JSON.stringify(arguments) // take a pseudo-array string as an argument
    cache[key] = cache[key] || fn.apply(fn, arguments)
    return cache[key]
  }
}
Copy the code

It’s OK to try

function getArea (r) {
  console.log(r);
  return Math.PI**r
}
let getAreaWithMemory = memoize(getArea)
console.log(getAreaWithMemory(4)) // Only 4 is printed, which is cached
console.log(getAreaWithMemory(4))
console.log(getAreaWithMemory(4))
Copy the code

Implement function combinationcompose

Simulate the flow method in LoDash

const reverse = arr= > arr.reverse();
const first = arr= > arr[0];
const toUpper = s= > s.toUpperCase();

const compose = (. fns) = > {
  return function (value) {
    return fns.reduce((acc, fn) = > {
      return fn(acc)
    }, value)
  }
}

const a = compose(reverse, first, toUpper)
console.log(a(['one'.'two'.'three']));
Copy the code

Use the arrow function shorthand

const compose = (. fns) = > value= > fns.reduce((acc, fn) = > fn(acc), value);
Copy the code

Analog implementationlodashIn thecurrymethods

  • Corrification allows us to pass in fewer arguments to a function and get a new function that has memorized some of the fixed arguments
  • This is a “cache” of function parameters, using closures
  • Make functions more flexible and smaller in granularity
  • You can convert multivariate functions into unary functions, and you can combine functions to produce powerful functions
function getSum(a, b, c) {
  return a + b + c
}
function curry (func) {
  return function curriedFn (. args) {
    // Determine the number of arguments and parameters
    if (args.length < func.length) { // method name. length => Get the number of parameters
      return function () { // Arguments
        // recursive call
        returncurriedFn(... args.concat(Array.from(arguments)))}}// Execute when the number of arguments and parameters is equal
    returnfunc(... args) } }const curried = curry(getSum)
// console.log(curried(1, 2, 3))
// console.log(curried(1, 2)(3))
console.log(curried(1) (2) (3))
Copy the code

Writing anewoperation

  1. The first kind of
function _new(fn, ... args) {
  let obj = Object.create(fn.prototype)
  fn.apply(obj, args)
  return obj
}
Copy the code

  1. The second way to write it
function New(Fn, ... args) {
  Create an empty object obj
  const obj = {};
  // 2. Point the __proto__ attribute of the object to the prototype of the constructor
  obj.__proto__ = Fn.prototype; 
  // 3. Bind the execution context (this) to the newly created object
  const result = Fn.apply(obj, args); 
  // 4. If the constructor returns a value of "reference type", return it. Otherwise return the object created above
  return result instanceof Object ? result : obj; 
}
Copy the code

bind,apply,callimplementation

  • Bind is poorly implemented and needs to be perfected in the case of new
Function.prototype.bind2 = function (context) {

    var self = this;
    // Get the bind2 function from the second argument to the last argument
    var args = Array.prototype.slice.call(arguments.1);

    return function () {
        // Arguments refer to the arguments passed in by the function returned by bind
        var bindArgs = Array.prototype.slice.call(arguments); self.apply(context, args.concat(bindArgs)); }}Copy the code
  • applyandcallThe implementation of the
Function.prototype.apply2 = function (context, array) {
    context = context || window
    context.fn = this;
    const result = context.fn(array)
    delete context.fn
    return result
}
let obj = {
    value: 2.test() {console.log(this.value)}
}
function test () {
    console.log(this.value)
}
test.apply2(obj);
Copy the code

varimplementationletBlock-level scoping characteristics

Since function arguments are passed by value, the current value of the index variable is copied to parameter I, and a closure is created inside the timer1 function that accesses variable I and returns different values

for (var index = 0; index < 5; index++) {
  (function timer1(i) {
     console.log(i);
  })(index);
}
Copy the code

implementationreduce

Array.prototype.myReduce = function (func, initialValue) {
    const arr = this
    let base = typeof initialValue === 'undefined' ? arr[0] : initialValue;
    const startIndex = typeof initialValue === 'undefined' ? 1 : 0;
    arr.slice(startIndex).forEach(function (val, index) {
        base = func(base, val, index + startIndex, arr)
    })
    return base
}
Copy the code

withreduceimplementationmap

if (!Array.prototype.mapUsingReduce) {
    Array.prototype.mapUsingReduce = function (callback, thisArg) {
        return this.reduce(function (accumulator, currentValue, currentIndex, sourceArray) {
            accumulator[currentIndex] = callback.call(thisArg, currentValue, currentIndex, sourceArray)
            returnaccumulator; }}}, [])const resp = [1.2.3].mapUsingReduce((currentValue, index, array) = > currentValue + index)
Copy the code

withreduceimplementationgroupBy

function groupBy(arr, property) {
  return arr.reduce((data, item) = > {
    const key = item[property];
    if(! data[key]) { data[key] = []; } data[key].push(item);return data;
  }, {});
}
Copy the code

implementationdomToJson

  const dom = document.getElementById('wrapper')
  function dom2Json(rootDom) {
    const obj = {}
    obj.tag = rootDom.tagName;
    obj.className = rootDom.className;
    obj.children = handleChildren(rootDom)
    return obj;
  }

  // recursive processing
  function handleChildren(rootDom) {
    const result = [];
    const childs = rootDom.children;
    if(! childs || childs.length ===0) {
      return result;
    }
    for (const child of childs) {
      const obj = {}
      obj.tag = child.tagName;
      obj.className = child.className;
      obj.children = handleChildren(child);
      result.push(obj);
    }
    return result;
  }
Copy the code

Implementing priority queuesPriorityQueue

Element attribute: priority

Methods: Add, out

function PriorityQueue() {
  let queue = []
  this.add = (item) = > {
    if (queue.length === 0) {
      queue.push(item)
    } else {
      for (let i = 0; i < queue.length; i++) {
        const element = queue[i];
        if (element < item) {
          queue.splice(i, 0, item) // Perform queue jumping
          return; // Terminate the function} } queue.push(item); }};this.out = () = > {
    return queue.shift()
  }
  this.print = () = > {
    returnqueue; }}const queue = new PriorityQueue()
Copy the code

Const arr =,0,0,1,0,0,0,0,0,1,0,0 [1];

Thinking is important!

Replace the 0 with 1, but the 1 and the 1 can’t be next to each other before.

const arr = [1.0.0.1.0.0.0.1.0.0];
const foo = (arr, n = 3) = > {
  let count = 0;
  const tempArr = arr.join(' ').split(1);
  tempArr.forEach((item) = > {
    if (item.length >= 3) {
      const arrLen = arr.length;
      count += Math.trunc(item.length / 2);
      // Handle both ends of the array separately
      if (arr[0= = =0 && arr[1= = =0 || arr[arrLen - 1= = =0 && arr[arrLen - 2= = =0) {
        count += 1; }}})return count === n
};
Copy the code

The number array is sorted by the size of the trailing digit

const sort = (arr) = > {
    arr.sort((a, b) = > a % 10 - b % 10)}Copy the code