67
头图

Preface

Hello, everyone. I’m Lin basis of 161a2dfdb3877e is the prerequisite for advanced 50 basic JS knowledge points and 50 advanced JS knowledge points this year’s notes of this rookie.

Today I will share with you the 56 JavaScript handwritten knowledge points in

Note: This article does not contain algorithm question

Frequent Interview Test

1. 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)
    }
}

2. The process of handwriting new

function myNew(fn, ...args) {

    const obj = {}

    obj.__proto__ = fn.prototype

    fn.apply(obj, args)

    return obj
}

3. Instanceof keyword

function instanceOf(father, child) {
    const fp = father.prototype
    var cp = child.__proto__

    while (cp) {
        if (cp === fp) {
            return true
        }
        cp = cp.__proto__
    }

    return false
}

4. Realize the anti-shake function

function debounce(fn, delay = 500) {
    let timer;
    return function () {
        if (timer) {
            clearTimeout(timer)
        }
        const args = arguments        
        timer = setTimeout(() => {
            fn.apply(this, args) // 改变this指向为调用debounce所指的对象
        }, delay)
    }
}

5. Realize the throttle function

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

6. Implement array deduplication

Title description: Realize the de-duplication of an array
// 第一种:Map记录
function quchong1(arr) {
    const newArr = []
    arr.reduce((pre, next) => {
        if (!pre[next]) {
            pre[next] = 1
            newArr.push(next)
        }
        return pre
    }, {})
    return newArr
}

// 第二种:Set去重
function quchong2(arr) {
    return [...new Set(arr)]
}

7. Use setTimeout to implement setInterval

Title description: Setinterval is used to implement cyclic timing calls. There may be certain problems. Can settimeout be used to solve
function mySetTimout(fn, delay) {
    let timer = null
    const interval = () => {
        fn()
        timer = setTimeout(interval, delay)
    }
    setTimeout(interval, delay)
    return {
        cancel: () => {
            clearTimeout(timer)
        }
    }
}

// 测试
const { cancel } = mySetTimout(() => console.log(888), 1000)
setTimeout(() => {
    cancel()
}, 4000)

8. Use setInterval to implement setTimeout

Title description: No, I just want to make things difficult for you
function mySetInterval(fn, delay) {
    const timer = setInterval(() => {
        fn()
        clearInterval(timer)
    }, delay)
}

// 测试
mySetInterval(() => console.log(888), 1000)

9, implement a compose function

Title description: Achieve the following effects
function fn1(x) {
    return x + 1;
}
function fn2(x) {
    return x + 2;
}
function fn3(x) {
    return x + 3;
}
function fn4(x) {
    return x + 4;
}
const a = compose(fn1, fn2, fn3, fn4);
console.log(a)
console.log(a(1)); // 1+2+3+4=11
The implementation is as follows:
function compose(...fn) {
    if (fn.length === 0) return (num) => num
    if (fn.length === 1) return fn[0]
    return fn.reduce((pre, next) => {
        return (num) => {
            return next(pre(num))
        }
    })
}

10. Implement a curried function

Subject requirements:
const add = (a, b, c) => a + b + c;
const a = currying(add, 1);
console.log(a(2,3)) // 1 + 2 + 3=6
The implementation is as follows:
function currying(fn, ...args1) {
  // 获取fn参数有几个
  const length = fn.length
  let allArgs = [...args1]
  const res = (...arg2) => {
    allArgs = [...allArgs, ...arg2]
    // 长度相等就返回执行结果
    if (allArgs.length === length) {
      return fn(...allArgs)
    } else {
      // 不相等继续返回函数
      return res
    }
  }
  return res
}

// 测试:
const add = (a, b, c) => a + b + c;
const a = currying(add, 1);
console.log(a(2,3))

11. Implement an LRU cache function

Title description:

image.png

The implementation is as follows:
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)
    }
  }

}

12. Simple implementation of publish and subscribe mode

Topic description: Implement a publish-subscribe model with on emit once off method
class EventEmitter {
    constructor() {
        this.cache = {}
    }

    on(name, fn) {
        const tasks = this.cache[name]
        if (tasks) {
            this.cache[name].push(fn)
        } else {
            this.cache[name] = [fn]
        }
    }

    off(name, fn) {
        const tasks = this.cache[name]
        if (task) {
            const index = tasks.findIndex(item => item === fn)
            if (index >= 0) {
                this.cache[name].splice(index, 1)
            }
        }
    }

    emit(name, once = false, ...args) {
        // 复制一份。防止回调里继续on,导致死循环
        const tasks = this.cache[name].slice()
        if (tasks) {
            for (let fn of tasks) {
                fn(...args)
            }
        }
        if (once) {
            delete this.cache[name]
        }
    }

    once(name, ...args) {
        this.emit(name, true, ...args)
    }
}

13, implement JSON.parse

Title description: Implement JSON.parse
function parse (json) {
    return eval("(" + json + ")");
}

14. Convert the DOM into a tree structure object

Title description:
<div>
    <span></span>
    <ul>
        <li></li>
        <li></li>
    </ul>
</div>

将上方的DOM转化为下面的树结构对象

{
    tag: 'DIV',
    children: [
        { tag: 'SPAN', children: [] },
        {
            tag: 'UL',
            children: [
                { tag: 'LI', children: [] },
                { tag: 'LI', children: [] }
            ]
        }
    ]
}
The implementation is as follows:
function dom2tree(dom) {
    const obj = {}
    obj.tag = dom.tagName
    obj.children = []
    dom.childNodes.forEach(child => obj.children.push(dom2tree(child)))
    return obj
}

15. Convert the tree structure to DOM

Title description:
{
    tag: 'DIV',
    children: [
        { tag: 'SPAN', children: [] },
        {
            tag: 'UL',
            children: [
                { tag: 'LI', children: [] },
                { tag: 'LI', children: [] }
            ]
        }
    ]
}

将上方的树结构对象转化为下面的DOM

<div>
    <span></span>
    <ul>
        <li></li>
        <li></li>
    </ul>
</div>
The implementation is as follows:
// 真正的渲染函数
function _render(vnode) {
  // 如果是数字类型转化为字符串
  if (typeof vnode === "number") {
    vnode = String(vnode);
  }
  // 字符串类型直接就是文本节点
  if (typeof vnode === "string") {
    return document.createTextNode(vnode);
  }
  // 普通DOM
  const dom = document.createElement(vnode.tag);
  if (vnode.attrs) {
    // 遍历属性
    Object.keys(vnode.attrs).forEach((key) => {
      const value = vnode.attrs[key];
      dom.setAttribute(key, value);
    });
  }
  // 子数组进行递归操作
  vnode.children.forEach((child) => dom.appendChild(_render(child)));
  return dom;
}

16, determine an object has a ring reference

Title description: Verify that an object has no loop references
var obj = {
    a: {
        c: [
            1, 2
        ]
    },
    b: 1
}
obj.a.c.d = obj
console.log(cycleDetector(obj)) // true
Implementation idea: use an array to store each traversed object, and the next time it finds the existence in the array, it means the ring reference
function cycleDetector(obj) {
    const arr = [obj]
    let flag = false

    function cycle(o) {
        const keys = Object.keys(o)
        for (const key of keys) {
            const temp = o[key]
            if (typeof temp === 'object' && temp !== null) {
                if (arr.indexOf(temp) >= 0) {
                    flag = true
                    return
                }
                arr.push(temp)
                cycle(temp)
            }
        }
    }

    cycle(obj)

    return flag
}

17. Calculate the number of layers of an object

Title description: Give you an object and count its layers
const obj = {
    a: { b: [1] },
    c: { d: { e: { f: 1 } } }
}

console.log(loopGetLevel(obj)) // 4
The implementation is as follows:
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
}

18. Flattening of objects

Title description:
const obj = {
  a: {
         b: 1,
         c: 2,
         d: {e: 5}
     },
  b: [1, 3, {a: 2, b: 3}],
  c: 3
 }
 
 flatten(obj) 结果返回如下
 // {
 //  'a.b': 1,
 //  'a.c': 2,
 //  'a.d.e': 5,
 //  'b[0]': 1,
 //  'b[1]': 3,
 //  'b[2].a': 2,
 //  'b[2].b': 3
 //   c: 3
 // }
The implementation is as follows:
const isObject = (val) =>  typeof val === "object" && val !== null

function flatten(obj) {
  if (!isObject(obj)) return
  const res = {}
  const dfs = (cur, prefix) => {
    if (isObject(cur)) {
      if (Array.isArray(cur)) {
        cur.forEach((item, index) => {
          dfs(item, `${prefix}[${index}]`)
        })
      } else {
        for(let key in cur) {
          dfs(cur[key], `${prefix}${prefix ? '.' : ''}${key}`)
        }
      }
    } else {
      res[prefix] = cur
    }
  }
  dfs(obj, '')
  return res
}

// 测试
console.log(flatten(obj))

19. Realize (a == 1 && a == 2 && a == 3) is true

Title description: implementation (a == 1 && a == 2 && a == 3) is true
// 第一种方法
var a = {
  i: 1,
  toString: function () {
    return a.i++;
  }
}
console.log(a == 1 && a == 2 && a == 3) // true

// 第二种方法
var a = [1, 2, 3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3); // true

// 第三种方法
var val = 0;
Object.defineProperty(window, 'a', {
    get: function () {
        return ++val;
    }
});
console.log(a == 1 && a == 2 && a == 3) // true

20. Implement a Promise scheduler that limits concurrency

Title description: JS implements an asynchronous scheduler Scheduler with concurrency restrictions, ensuring that there are at most two tasks running at the same time
addTask(1000,"1");
addTask(500,"2");
addTask(300,"3");
addTask(400,"4");
的输出顺序是:2 3 1 4

整个的完整执行流程:

一开始1、2两个任务开始执行
500ms时,2任务执行完毕,输出2,任务3开始执行
800ms时,3任务执行完毕,输出3,任务4开始执行
1000ms时,1任务执行完毕,输出1,此时只剩下4任务在执行
1200ms时,4任务执行完毕,输出4
The implementation is as follows:
class Scheduler {
  constructor(limit) {
    this.queue = []
    this.limit = limit
    this.count = 0
  }
  

  add(time, order) {
    const promiseCreator = () => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log(order)
          resolve()
        }, time)
      })
    }
    this.queue.push(promiseCreator)
  }

  taskStart() {
    for(let i = 0; i < this.limit; i++) {
      this.request()
    }
  }

  request() {
    if (!this.queue.length || this.count >= this.limit) return
    this.count++
    this.queue.shift()().then(() => {
      this.count--
      this.request()
    })
  }
}

// 测试
const scheduler = new Scheduler(2);
const addTask = (time, order) => {
  scheduler.add(time, order);
};
addTask(1000, "1");
addTask(500, "2");
addTask(300, "3");
addTask(400, "4");
scheduler.taskStart();

21. Implement lazyMan function

Title description:
实现一个LazyMan,可以按照以下方式调用:
LazyMan(“Hank”)输出:
Hi! This is Hank!

LazyMan(“Hank”).sleep(10).eat(“dinner”)输出
Hi! This is Hank!
//等待10秒..
Wake up after 10
Eat dinner~

LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出
Hi This is Hank!
Eat dinner~
Eat supper~

LazyMan(“Hank”).eat(“supper”).sleepFirst(5)输出
//等待5秒
Wake up after 5
Hi This is Hank!
Eat supper
The implementation is as follows:
class _LazyMan {
  constructor(name) {
    this.tasks = []
    const task = () => {
      console.log(`Hi! This is ${name}`)
      this.next()
    }
    this.tasks.push(task)
    setTimeout(() => {
      this.next()
    }, 0)
  }
  next() {
    const task = this.tasks.shift()
    task && task()
  }
  sleep(time) {
    this.sleepWrapper(time, false)
    return this
  }
  sleepFirst(time) {
    this.sleepWrapper(time, true)
    return this
  }
  sleepWrapper(time, first) {
    const task = () => {
      setTimeout(() => {
        console.log(`Wake up after ${time}`)
        this.next()
      }, time * 1000)
    }
    if (first) {
      this.tasks.unshift(task)
    } else {
      this.tasks.push(task)
    }
  }
  eat(food) {
    const task = () => {
      console.log(`Eat ${food}`);
      this.next();
    };
    this.tasks.push(task);
    return this;
  }
}

// 测试
const lazyMan = (name) => new _LazyMan(name)

lazyMan('Hank').sleep(1).eat('dinner')

lazyMan('Hank').eat('dinner').eat('supper')

lazyMan('Hank').eat('supper').sleepFirst(5)

22, implement the add function

Title description: Implement an add method so that the calculation result can meet the following expectations:

  • add(1)(2)(3)()=6
  • add(1,2,3)(4)()=10
function add(...args1) {
  let allArgs = [...args1]

  function fn(...args2) {
    if (!args2.length) return fn.toString()
    allArgs = [...allArgs, ...args2]
    return fn
  }

  fn.toString = function () {
    return allArgs.reduce((pre, next) => pre + next)
  }

  return fn
}

// 测试
console.log(add(1)(2)(3)())
console.log(add(1, 2)(3)())

23. Realize a qualified deep copy

I recommend reading this article: deep copy has these 5 ranks, are you just a bronze rank? Still want a salary increase?

24. Realize Promise

I recommend reading this article: will read it, handwritten Promise principle, the most easy-to-understand version! ! ! 【Reading: 1.3w, Like: 460】

25, implement async/await

I recommend reading this article: 7 pictures, async/await principle that can be done in 20 minutes! Why did it take so long? 【Reading: 2.15w, Like: 460】

Array articles

Define a test array

const players = [
    { name: '科比', num: 24 },
    { name: '詹姆斯', num: 23 },
    { name: '保罗', num: 3 },
    { name: '威少', num: 0 },
    { name: '杜兰特', num: 35 }
]

26、forEach

The meaning of the parameter

  • item: traverse item
  • index: the index of the traversed item
  • arr: the array itself

    Array.prototype.sx_forEach = function (callback) {
      for (let i = 0; i < this.length; i++) {
          callback(this[i], i, this)
      }
    }
    
    players.sx_forEach((item, index, arr) => {
      console.log(item, index)
    })
    // { name: '科比', num: 24 } 0
    // { name: '詹姆斯', num: 23 } 1
    // { name: '保罗', num: 3 } 2
    // { name: '威少', num: 0 } 3
    // { name: '杜兰特', num: 35 } 4

    27、map

    The meaning of the parameter

  • item: traverse item
  • index: the index of the traversed item
  • arr: the array itself

    Array.prototype.sx_map = function (callback) {
      const res = []
      for (let i = 0; i < this.length; i++) {
          res.push(callback(this[i], i, this))
      }
      return res
    }
    
    console.log(players.sx_map((item, index) => `${item.name}--${item.num}--${index}`))
    // [ '科比--24--0', '詹姆斯--23--1', '保罗--3--2', '威少--0--3', '杜兰特--35--4' ]

    28、filter

    The meaning of the parameter

  • item: traverse item
  • index: the index of the traversed item
  • arr: the array itself

    Array.prototype.sx_filter = function (callback) {
      const res = []
      for (let i = 0; i < this.length; i++) {
          callback(this[i], i, this) && res.push(this[i])
      }
      return res
    }
    
    console.log(players.sx_filter(item => item.num >= 23))
    // [
    //     { name: '科比', num: 24 },
    //     { name: '詹姆斯', num: 23 },
    //     { name: '杜兰特', num: 35 }
    // ]

    29、every

    The meaning of the parameter

  • item: traverse item
  • index: the index of the traversed item
  • arr: the array itself

    Array.prototype.sx_every = function (callback) {
      let flag = true
      for (let i = 0; i < this.length; i++) {
          flag = callback(this[i], i, this)
          if (!flag) break
      }
    
      return flag
    }
    
    console.log(players.sx_every(item => item.num >= 23)) // false
    console.log(players.sx_every(item => item.num >= 0)) // true

    30、some

    The meaning of the parameter

  • item: traverse item
  • index: the index of the traversed item
  • arr: the array itself

    Array.prototype.sx_some = function (callback) {
      let flag = false
      for (let i = 0; i < this.length; i++) {
          flag = callback(this[i], i, this)
          if (flag) break
      }
    
      return flag
    }
    
    console.log(players.sx_some(item => item.num >= 23)) // true
    console.log(players.sx_some(item => item.num >= 50)) // false

31、reduce

The meaning of the parameter

  • pre: the previous item
  • next: next item
  • index: current index
  • arr: the array itself

    Array.prototype.sx_reduce = function (callback, initValue) {
      let start = 0, pre
      if (initValue) {
          pre = initValue
      } else {
          pre = this[0]
          start = 1
      }
      for (let i = start; i < this.length; i++) {
          pre = callback(pre, this[i], i, this)
      }
      return pre
    }
    
    // 计算所有num相加
    const sum = players.sx_reduce((pre, next) => {
      return pre + next.num
    }, 0)
    console.log(sum) // 85

32、findIndex

The meaning of the parameter

  • item: traverse item
  • index: the index of the traversed item
  • arr: the array itself

    Array.prototype.sx_findIndex = function (callback) {
      for (let i = 0; i < this.length; i++) {
          if (callback(this[i], i, this)) {
              return i
          }
      }
      return -1
    }
    
    console.log(players.sx_findIndex(item => item.name === '科比')) // 0
    console.log(players.sx_findIndex(item => item.name === '安东尼')) // -1

33、find

The meaning of the parameter

  • item: traverse item
  • index: the index of the traversed item
  • arr: the array itself

    Array.prototype.sx_find = function (callback) {
      for (let i = 0; i < this.length; i++) {
          if (callback(this[i], i, this)) {
              return this[i]
          }
      }
      return undefined
    }
    
    console.log(players.sx_find(item => item.name === '科比')) // { name: '科比', num: 24 }
    console.log(players.sx_find(item => item.name === '安东尼')) // undefined

34、fill

Use: Fill the array

The meaning of the parameter

  • initValue: filled value
  • start: start filling index, default 0
  • end: end filling index, default length
Array.prototype.sx_fill = function (value, start = 0, end) {
  end = end || this.length
  for (let i = start; i < end; i++) {
      this[i] = value
  }
  return this
}

console.log(players.sx_fill('林三心', 1, 3))
// [
//     { name: '科比', num: 24 },
//     '林三心',
//     '林三心',
//     '林三心',
//     { name: '杜兰特', num: 35 }
// ]

35、includes

Use: Find the element, if it finds it, it returns true , otherwise it returns false , it can find NaN

Array.prototype.sx_includes = function (value, start = 0) {
    if (start < 0) start = this.length + start
    const isNaN = Number.isNaN(value)
    for (let i = start; i < this.length; i++) {
        if (this[i] === value || Number.isNaN(this[i]) === isNaN) {
            return true
        }
    }
    return false
}

console.log([1, 2, 3].sx_includes(2)) // true
console.log([1, 2, 3, NaN].sx_includes(NaN)) // true
console.log([1, 2, 3].sx_includes(1, 1)) // false

36、join

, array with a delimiter into a string, the default delimiter is 061a2dfdb394db

Array.prototype.sx_join = function (s = ',') {
    let str = ''
    for(let i = 0; i < this.length; i++) {
        str = i === 0 ? `${str}${this[i]}` : `${str}${s}${this[i]}`
    }
    return str
}

console.log([1, 2, 3].sx_join()) // 1,2,3
console.log([1, 2, 3].sx_join('*')) // 1*2*3

37、flat

Array.prototype.sx_flat = function () {
    let arr = this
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr)
    }
    return arr
}

const testArr = [1, [2, 3, [4, 5]], [8, 9]]

console.log(testArr.sx_flat())
// [1, 2, 3, 4, 5, 8, 9]

38、splice

difficulty

  • Comparison of interception length and replacement length, different situations

    Array.prototype.sx_splice = function (start, length, ...values) {
    length = start + length > this.length - 1 ? this.length - start : length
    const res = [], tempArr = [...this]
    for (let i = start; i < start + values.length; i++) {
      this[i] = values[i - start]
    }
    if (values.length < length) {
      const cha = length - values.length
      for (let i = start + values.length; i < tempArr.length; i++) {
        this[i] = tempArr[i + cha]
      }
      this.length = this.length - cha 
    }
    if (values.length > length) {
      for (let i = start + length; i < tempArr.length; i++) {
        this.push(tempArr[i])
      }
    }
    for (let i = start; i < start + length; i++) {
      res.push(tempArr[i])
    }
    return res
    }

Object articles

Define a test object

const obj = {
    name: '林三心',
    age: 22,
    gender: '男'
}

39、entries

Use: Turn the object into an array of key-value pairs

Object.prototype.sx_entries = function (obj) {
    const res = []
    for (let key in obj) {
        obj.hasOwnProperty(key) && res.push([key, obj[key]])
    }
    return res
}

console.log(Object.sx_entries(obj))
// [ [ 'name', '林三心' ], [ 'age', 22 ], [ 'gender', '男' ] ]

40、fromEntries

Use: entries , convert an array of key-value pairs into objects

Object.prototype.sx_fromEntries = function (arr) {
    const obj = {}
    for (let i = 0; i < arr.length; i++) {
        const [key, value] = arr[i]
        obj[key] = value
    }
    return obj
}

console.log(Object.sx_fromEntries([['name', '林三心'], ['age', 22], ['gender', '男']]))
// { name: '林三心', age: 22, gender: '男' }

41、keys

Use: Turn the key of the object into a set of numbers

Object.prototype.sx_keys = function (obj) {
    const keys = []
    for (let key in obj) {
        obj.hasOwnProperty(key) && res.push(key)
    }
    return keys
}

console.log(Object.keys(obj))
// [ 'name', 'age', 'gender' ]

42、values

Use: Turn all the values of the object into a set of numbers

Object.prototype.sx_values = function (obj) {
    const values = []
    for (let key in obj) {
        obj.hasOwnProperty(key) && values.push(obj[key])
    }
    return values
}

console.log(Object.sx_values(obj))
// [ '林三心', 22, '男' ]

43、instanceOf

Use: A instanceOf B, to determine whether A passes through the prototype chain of B

function instanceOf(father, child) {
    const fp = father.prototype
    var cp = child.__proto__

    while (cp) {
        if (cp === fp) {
            return true
        }
        cp = cp.__proto__
    }

    return false
}

function Person(name) {
    this.name = name
}
const sx = new Person('林三心')

console.log(instanceOf(Person, sx)) // true
console.log(instanceOf(Person, sx2)) // false

44、is

Use: Object.is(a, b), to determine whether a is equal to b

Object.prototype.sx_is = function (x, y) {
    if (x === y) {
        // 防止 -0 和 +0
        return x !== 0 || 1 / x === 1 / y
    }

    // 防止NaN
    return x !== x && y !== y
}

const a = { name: '林三心' }
const b = a
const c = { name: '林三心' }

console.log(Object.sx_is(a, b)) // true
console.log(Object.sx_is(a, c)) // false

45、Object.assign

difficulty

  • assign receives multiple objects and combines multiple objects into one object
  • If these objects have attributes with the same name, the attribute values of the future objects shall prevail
  • assign returns an object, this object === the first 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
    }
    
    const testa = { name: '林三心' }
    const testb = { name: 'sunshine_lin', age: 22 }
    const testc = { age: 18, gender: '男' }
    
    const testd = Object.sx_assign(testa, testb, testc)
    console.log(testd) // { name: 'sunshine_lin', age: 18, gender: '男' }
    console.log(testa === testd) // true

Function

46、call

Function.prototype.sx_call = function (obj, ...args) {
    obj = obj || window

    // Symbol是唯一的,防止重名key
    const fn = Symbol()
    obj[fn] = this

    // 执行,返回执行值
    return obj[fn](...args)
}

const testobj = {
    name: '林三心',
    testFn(age) {
        console.log(`${this.name}${age}岁了`)
    }
}
const testobj2 = {
    name: 'sunshine_lin'
}

testobj.testFn.sx_call(testobj2, 22) // sunshine_lin22岁了

47、apply

Function.prototype.sx_apply = function (obj, args) {
    obj = obj || window

    // Symbol是唯一的,防止重名key
    const fn = Symbol()
    obj[fn] = this

    // 执行,返回执行值
    return obj[fn](...args)
}

const testobj = {
    name: '林三心',
    testFn(age) {
        console.log(`${this.name}${age}岁了`)
    }
}
const testobj2 = {
    name: 'sunshine_lin'
}

testobj.testFn.sx_apply(testobj2, [22]) // sunshine_lin22岁了

48、Function.prototype.bind

difficulty:

  • bind is to return a function, not the execution result
  • The function returned by bind is used as a constructor, how to deal with it

    Function.prototype.sx_bind = function (obj, ...args) {
      obj = obj || window
    
      // Symbol是唯一的,防止重名key
      const fn = Symbol()
      obj[fn] = this
      const _this = this
    
      const res = function (...innerArgs) {
          console.log(this, _this)
          if (this instanceof _this) {
              this[fn] = _this
              this[fn](...[...args, ...innerArgs])
              delete this[fn]
          } else {
              obj[fn](...[...args, ...innerArgs])
              delete obj[fn]
          }
      }
      res.prototype = Object.create(this.prototype)
      return res
    }

String articles

49、slice

The meaning of the parameter

  • start: The index of the character to start intercepting (including this character)
  • end: the index of the character to end the interception (not including this character)
    be careful
  • start> end: return an empty string
  • start <0: start = array length + start
String.prototype.sx_slice = 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
}

console.log(str.sx_slice(2)) // nshine_lin
console.log(str.sx_slice(-2)) // in
console.log(str.sx_slice(-9, 10)) // shine_l
console.log(str.sx_slice(5, 1)) // ''

50、substr

The meaning of the parameter

  • start: The index of the character to start intercepting (including this character)
  • length: the length of the interception
    be careful
  • start <0: start = array length + start
  • Length exceeds the range that can be intercepted and needs to be processed
  • length <0: return an empty string
String.prototype.sx_substr = 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
}

console.log(str.sx_substr(3)) // shine_lin
console.log(str.sx_substr(3, 3)) // shi
console.log(str.sx_substr(5, 300)) // ine_lin

51、substring

The function is roughly the same as slice

Difference

  • start> end: swap value

    String.prototype.sx_sunstring = 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
    }
    
    console.log(str.sx_sunstring(2)) // nshine_lin
    console.log(str.sx_sunstring(-2)) // in
    console.log(str.sx_sunstring(-9, 10)) // shine_l
    console.log(str.sx_sunstring(5, 1)) // unsh

Promise

52、all

  • Receive a Promise array, if there is a non-Promise item in the array, this item is considered as a success
  • If all Promises succeed, return an array of successful results
  • If a Promise fails, return this failure result

      function all(promises) {
          const result = []
          let count = 0
          return new MyPromise((resolve, reject) => {
              const addData = (index, value) => {
                  result[index] = value
                  count++
                  if (count === promises.length) resolve(result)
              }
              promises.forEach((promise, index) => {
                  if (promise instanceof MyPromise) {
                      promise.then(res => {
                          addData(index, res)
                      }, err => reject(err))
                  } else {
                      addData(index, promise)
                  }
              })
          })
      }

    53、race

  • Receive a Promise array, if there is a non-Promise item in the array, this item is considered as a success
  • Which Promise gets the fastest result will return that result, regardless of success or failure

      function race(promises) {
          return new MyPromise((resolve, reject) => {
              promises.forEach(promise => {
                  if (promise instanceof MyPromise) {
                      promise.then(res => {
                          resolve(res)
                      }, err => {
                          reject(err)
                      })
                  } else {
                      resolve(promise)
                  }
              })
          })
      }

    54、allSettled

  • Receive a Promise array, if there is a non-Promise item in the array, this item is considered as a success
  • Collect the results of each Promise into an array and return

      function allSettled(promises) {
          return new Promise((resolve, reject) => {
              const res = []
              let count = 0
              const addData = (status, value, i) => {
                  res[i] = {
                      status,
                      value
                  }
                  count++
                  if (count === promises.length) {
                      resolve(res)
                  }
              }
              promises.forEach((promise, i) => {
                  if (promise instanceof MyPromise) {
                      promise.then(res => {
                          addData('fulfilled', res, i)
                      }, err => {
                          addData('rejected', err, i)
                      })
                  } else {
                      addData('fulfilled', promise, i)
                  }
              })
          })
      }

    55、any

    any is the opposite of all

  • Receive a Promise array, if there is a non-Promise item in the array, this item is considered as a success
  • If a Promise succeeds, return this successful result
  • If all Promises fail, an error is reported

      function any(promises) {
          return new Promise((resolve, reject) => {
              let count = 0
              promises.forEach((promise) => {
                  promise.then(val => {
                      resolve(val)
                  }, err => {
                      count++
                      if (count === promises.length) {
                          reject(new AggregateError('All promises were rejected'))
                      }
                  })
              })
          })
      }
    }

    56、finally

  • Receive a callback function, but receive no parameters
  • Regardless of the success or failure status, finally will be executed

    Promise.prototype.finally = function(callback) {
    return this.then(res => {
      callback()
      return res
    }, err => {
      callback()
      throw err
    })
    }

    Concluding remarks

If you think this article is of little help to you, please give me a thumbs up and encourage Lin Sanxin haha. Or you can join my fish-fishing group. Let's study hard together, ah, ah, ah, ah, I will mock interviews regularly, resume guidance, answer questions and answer questions, let's learn from each other and make progress together! !
截屏2021-11-28 上午9.43.19.png


Sunshine_Lin
2.1k 声望7.1k 粉丝