1. Write a call

  • Symbol is a string in the object attribute names of Es5, and when the attribute names of an object are duplicated, the latter tends to override the former. Using Symbol can ensure that the name of each attribute is unique, which is equivalent to generating a unique identifier ID, thus fundamentally preventing attribute name conflicts
Function.prototype.myCall = function (context, ... Args) {// Destruct context and arguments if (typeof this! == 'function') {throw new TypeError('must be a function'); } if (! Context) {// There is no context, or null undefined, reset to window context = window; } const fn = Symbol(); Context [fn] = this; context[fn] = this; // Add this to the attributes of the context const result = context[fn](... args); Delete context[fn]; // Delete context symbol property return result; // Return the return value}; // const bar = {a: 1}; function foo(b) { console.log(this.a, b); return this.a + b; } console.log(foo.myCall(bar, 2));Copy the code

2. Write apply by hand

Function. The prototype. MyApply = Function (the context, the args = []) {/ / to deconstruct the context and the arguments of the if (typeof this! == 'function') {throw new TypeError('must be a function'); } if (! Context) {// There is no context, or null undefined, reset to window context = window; } context.fn = this; // Add this to the property of the context const result = context.fn(... args); // Call the context's fn delete context.fn; // Delete new context s return result; // Return the return value}; // const bar = {a: 1}; function foo(b) { console.log(this.a, b); return this.a + b; } console.log(foo.myApply(bar, [2]));Copy the code

3. Handwritten bind

Function.prototype.myBind = function(context,... args) { const fn = this; if(typeof fn ! == "function"){ throw new TypeError("it must be a function") } if(! context){ context = window; } return function (... otherArgs) { return fn.apply(context,[...args,...otherArgs]); } // const bar = {a:1,}; function foo(b,c,d) { console.log(this.a,b,c,d) // 1 2 3 4 return this.a+b+c+d; } const fn = foo.mybind (bar,2) console.log(fn(3,4))Copy the code

4, to achieve anti-shake

  • After the conceptual event is triggered, the function is executed only once for n seconds. If the event is triggered again within n seconds, the function execution time is recalculated
function debounce(func, delay){ let timer; return function() { console.log('debounce: return: ',arguments); clearTimeout(timer) timer = setTimeout(()=>{ func(arguments) },delay) } } const aa = debounce((... Args)=>{console.log('debounce: executed ',... args) },3000); aa('aa','bb');Copy the code

5. Realize throttling

  • Concept fires events continuously, but only once in n seconds
function throttleOne (func, delay){ let preTime =0; Const nowTime = date.now () if(nowtime-pretime >delay){return function(){// date.now () const nowTime = date.now () if(nowtime-pretime >delay){return function(){// date.now () const nowTime = date.now () if(nowtime-pretime >delay){ func(arguments) preTime=nowTime; } } } function throttleTwo (func, delay){ let isStart = true; return function(){ if(isStart){ isStart=false setTimeout(() => { func(arguments) isStart = true }, delay); }}} const bb = throttleTwo((... Args)=>{console.log('throttle: executed ',... args) },5000); bb('aa','bb');Copy the code

6, handwritten promise.all

const isPromise = value => typeof value.then === 'function'; Promise. All = function(Promise) {return new Promise((resolve, reject) => { Let arr = []; let arr = []; let index = 0; const processData = (key, data) => { arr[key] = data; If (++index === promises. Length){resolve(arr); } } for (let i = 0; i < promises.length; i++) { let result = promises[i]; if (isPromise(result)) { result.then((data) => { processData(i, data) }, reject) } else { processData(i, result) } } });  } let p1 = new Promise((resolve, reject) => {reject(' reject ')}) let p2 = new Promise((resolve, reject) reject) => { resolve('success') }) Promise.all([p1,p2]).then((res)=>{ console.log('-result-',res) })Copy the code

7. Write promise.race

const isPromise = value => typeof value.then === 'function'; Promise.race = function(promises) { return new Promise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { let result = promises[i]; if(isPromise(result)){ result.then(resolve,reject) }else{ resolve(result); }}}); Then ((res)=>{console.log('result: ',res)})Copy the code

8. Handwritten inheritance

Const arr = [{"1":1},2,3,5]; // const arr = [{"1":1},2,3,5]; // object.create Creates a new Object, Function Parent(){this.name ="father"; function Parent(){this.name ="father"; this.age = 11; } parent.prototype. say= function (){console.log(' dad is talking ')} Function Child(color){Parent. Call (this) this.color = color; } Child.prototype = Object.create(Parent.prototype); Child.prototype.constructor = Child; /* prototype = new Parent(); /* prototype = new Parent(); Const child1 = new Child(' yellow '); / / const child1 = new Child(' yellow '); Const child2 = new Child(' yellow '); const parent1 = new Parent(); console.log(child1.constructor) console.log(child2.constructor) console.log(parent1.constructor)Copy the code

Write new by hand

  • A. Create an empty simple JavaScript object (that is {});
  • B. Link this object (that is, set its constructor) to another object; (Commonly understood as the new object’s implicit prototype proto is linked to the constructor’s explicit prototype.)
  • C. Use the object created in Step 1 as the context of this. (The constructor is actually executed and scoped to the new object)
  • D. If the function does not return an object, return this. New Object() returns an empty Object {}
function myNew(fn, ... args) { let obj = Object.create(fn.prototype); let res = fn.call(obj, ... args); if (res && (typeof res === "object" || typeof res === "function")) { return res; } return obj; // // function Person(name, age) {// // this.name = name; // // this.age = age; // // } // // Person.prototype.say = function() { // // console.log(this.age); / / / /}; // // let p1 = myNew(Person, "lihua", 18); // // console.log(p1.name); // // console.log(p1); // // p1.say();Copy the code

10, hand-written setTimeout simulation setInterval

function mySetInterval(fun, time) { let timer = null; Function setIntervalMe() {if (timer) {clearTimeout(timer); } timer = setTimeout(() => { fun(); setIntervalMe(fun, time); }, time); } setIntervalMe(); Return () => {// Clear clearTimeout(timer). }; } // use const cancel = mySetInterval(() => {console.log('aa', new Date())); }, 2000); setTimeout(() => { cancel(); }, 5000);Copy the code

11. Simple implementation of virtual DOM conversion into real DOM

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title>. 500px; width: 500px; background-color: bisque; } </style> </head> <body> <div id="root"></div> <script> const vnode = { tag: 'DIV', attrs: { id: 'app', class: 'app' }, children: [ { tag: 'DIV', attrs: { style: { height: '100px', width: '100px', backgroundColor: 'blue' } }, children: [ { tag: 'A', attrs: { style: { color: '#fff' } }, children: [{ value: 'hello word' }] } ] }, { tag: 'SPAN', children: [ { tag: 'A', children: [] }, { tag: 'A', children: [] } ] } ] }; Function _render(vnode) {if (typeof vnode. Tag! == 'string') { return document.createTextNode(vnode.value); } const dom = document.createElement(vnode.tag); Attrs) {for (let key in vnode.attrs) {if (key === 'style') {for (let styleName in vnode.attrs[key]) { dom.style[styleName] = vnode.attrs[key][styleName]; } } else { dom.setAttribute(key, vnode.attrs[key]); }}} vnode.children && vnode.children. ForEach (child => {// create a recursive child node, AppendChild (_render(child)); return dom.appendChild(_render(child)); }); // return dom if it is not a tag; } const nodes = _render(vnode); document.getElementById('root').appendChild(nodes); </script> </body> </html>Copy the code

12, real DOM conversion virtual DOM simple implementation

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, "/> <title>Document</title> </head> <body> <div id="root" class="tt" style="height: 100px; width: 100px; background-color: bisque"> <div title="tt1">hello1</div> </div> <script> class VNode { constructor(tag, attrs, value, type) { this.tag = tag && tag.toLowerCase(); this.attrs = attrs; this.value = value; this.type = type; this.children = []; } appendChild(vnode) { this.children.push(vnode); } } function getVNode(node) { const nodeType = node.nodeType; let _vnode = null; If (nodeType === 1) {// Const nodeName = node.nodename; const attrs = Array.from(node.attributes); // Class array let _attrObj = {}; attrs && attrs.forEach(item => { _attrObj[item.nodeName] = item.nodeValue; }); _vnode = new VNode(nodeName, _attrObj, undefined, nodeType); const childNodes = node.childNodes; childNodes.forEach(childNode => { _vnode.appendChild(getVNode(childNode)); }); } else if (nodeType === 3) {// text node_vnode = new VNode(undefined, undefined, node.nodeValue, nodeType); } return _vnode; } const root = document.getElementById('root'); const vRoot = getVNode(root); console.log(vRoot); console.log(JSON.stringify(vRoot)); </script> </body> </html>Copy the code

13. Handwriting – The Flatten method for implementing an object (Ali)

const obj = { a: { b: 1, c: 2, d: { e: 5 } }, b: [1, 3, { a: 2, b: 3 }, [1, 2]], c: 3 }; // integrated recurse, with different processing of objects and arrays let flattening obj = {}; function flatten(obj = {}, pre) { if (typeof obj === 'object' && ! Array.isarray (obj)) {for (let key in obj) {if (typeof obj[key]! == 'object') { flattenObj[`${pre ? pre + '.' : ''}${key || ''}`] = obj[key]; } else { const pre1 = pre ? `${pre}.${key}` : key; flatten(obj[key || ''], pre1); }}} else if (array.isarray (obj)) {console.log('flatten ', obj, pre); obj.forEach((item, index) => { const pre1 = `${pre}[${index}]`; if (typeof item === 'object') { flatten(item, pre1); } else { flattenObj[`${pre1}`] = item; }}); } return flattenObj; } // Console. log(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, // 'b[3][0]': 1, // 'b[3][1]': 2, // c: 3 // }Copy the code