1 Javascript based
1.1 handwritten Object. The create
The object.create () method creates a new Object, using an existing Object to provide the __proto__ of the newly created Object.
Solution: Use incoming objects as prototypes.
function create(obj) {
const A = function() {};
A.prototype = obj;
return new A();
}
Copy the code
1.2 handwritten instanceof
The instanceof operator is used to check whether the constructor’s prototype property appears on the prototype chain of an instance object.
Solution:
- Get the prototype of the type
- Gets the prototype of the object
- The prototype of the recursive loop object is then typed until NULL (the end of the prototype chain), false if different, and true if identical
function NewInstanceOf(source, target) {
if (typeofsource ! = ='object') {
return false;
}
// We can also use a while loop here
if(source.__proto__ ! == target.prototype) {if (source.__proto__ === null) {
return false;
}
return NewInstanceOf(source.__proto__, target);
}
return true;
}
Copy the code
1.3 Handwritten New operation symbol
The new operator creates an instance of a user-defined object type or of a built-in object with a constructor.
New will go through the following process:
- First, a new object is created
- Set the object prototype to the function prototype
- Set function this to point to this object, executing constructor code (set function properties to object properties)
- Determines the current return type and returns the create object if it is a value type or the reference object if it is a reference type.
const newFunc = (obj, ... args) = > {
let newObj = null;
if (typeofobj ! = ='function') {
throw ('type error');
}
newObj = Object.create(obj.prototype);
const result = obj.apply(newObj, args);
if (result && (typeof result === 'function' || typeof result === 'function')) {
return result;
}
return newObj;
}
Copy the code
1.4 Handwriting anti-shake function
If the event is triggered again within n seconds, the timer will be reset.
This can be used on some click-request events to avoid sending multiple requests to the back end because the user clicks multiple times.
function debounce(fn, time) {
let timer = null;
return function (. args) {!!!!! timer &&window.clearTimeout(timer);
timer = setTimeout(() = > fn(...args), time);
}
}
Copy the code
1.5 Handwriting throttling function
If an event is triggered more than once in the same unit of time, only one callback can take effect.
Throttling can be used to reduce the frequency of event calls through event throttling on scroll function event listeners.
function throttle(fn, time) {
let timer = null;
return function (. args) {
if (timer) {
return;
}
timer = setTimeout(() = > {
window.clearTimeout(timer);
timer = null;
fn(...args);
}, time);
}
}
Copy the code
1.6 Handwriting judgment type function
Solution: mainly for the typeof do distinguish for object, using object. The prototype. ToString object type information.
function computedType(arg) {
if (null === arg) {
return 'null';
}
if (typeof arg === 'object') {
const str = Object.prototype.toString.call(arg);
return str.replace(/ / \].' ').split(' ') [1];
}
return typeof arg;
}
Copy the code
1.7 Handwritten Call function
Solution:
- Determine whether the calling object is a function, even if we define it on the function prototype, but there may be calls such as call
- Checks whether the context-passed object exists, otherwise returns window
- You need to call this method as a property of the context object, save the result and return it
- Delete the new attribute of the context function, and return the result
Function.prototype.newCall = function(context = window. args) {
if (typeof this! = ='function') {
throw('type error');
}
context._fn = this;
constresult = context._fn(... args);delete context._fn;
return result;
}
Copy the code
1.8 Handwritten Apply function
Resolve the backlash: The implementation is similar to call, except that the parameters need to be handled briefly.
Function.prototype.newApply = function(context = window, args) {
if (typeof this! = ='function') {
throw('type error');
}
context._fn = this;
constresult = context._fn(... args);delete context._fn;
return result;
}
Copy the code
1.9 Handwritten bind function
Bind needs to return a function. In addition to the context execution object, there are also parameters of the function execution context.
Function.prototype.newBind = function(context = window. args) {
if (typeof this! = ='function') {
throw('type error');
}
context.fn = this;
return function (. newArgs) {
constresult = context.fn(... args, ... newArgs);delete context.fn;
returnresult; }}Copy the code
1.10 Currization of functions
Resolution: Call a function by passing it only a few arguments and having it return a function to process the rest.
function curry(fn, ... args) {
// The main point here is:
// 1. Use fn.length to get the length of the function argument
// 2. Returns a closure function that accumulates the length of arguments when the length is less than the length
returnargs.length === fn.length ? fn(... args) :(. newArgs) = >curry(fn, ... args, ... newArgs); }Copy the code
2 Data Conversion
2.1 Exchange a and B values without using temporary variables
Solution: Calculate the difference by subtracting and adding two numbers.
a = a + b;
b = a - b;
a = a - b;
Copy the code
In addition, js high-level syntax can be used for exchange.
[a, b] = [b, a];
Copy the code
2.2 Realize out-of-order output of data
Solution: Iterate from 0 to generate a random number, no less than the current number, and swap the random number with the current value until the end of the array.
function renderRandomArray(arr = []) {
for(let i = 0; i < arr.length; i++) {
const random = i + Math.round(Math.random() * (arr.length - i - 1));
[arr[i], arr[random]] = [arr[random], arr[i]];
}
return arr;
}
Copy the code
2.3 Array flattening
Solution: Recurse
function flatten(arr) {
let result = [];
for(let i = 0; i < arr.length; i++) {
if(Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
} else{ result.push(arr[i]); }}return result;
}
Copy the code
2.4 Data deduplication
Solution: Map
function uniqueArray(arr) {
let map = {};
let newArr = [];
for (const i of arr) {
if(! map[i]) { map[i] =true; newArr.push(i); }}return newArr;
}
Copy the code
2.5 Convert JS objects into tree results
// Before conversion:
source = [
{ id: 1.parentId: 0.name: 'rank1' },
{ id: 2.parentId: 1.name: 'rank2' },
{ id: 3.parentId: 2.name: 'rank3'}]// Convert to:
tree = [{
id: 1.parentId: 0.name: 'rank1'.children: [{
id: 2.parentId: 1.name: 'rank2'.children: [{ id: 3.parentId: 1.name: 'rank3'}}}]]]Copy the code
Solution:
- Create a map with the id of each item as the key and the value as the value.
- Set temporary variable result, traverse the number group and judge whether there is a parent node. If so, take out the parent node and set children of the parent node as this item. If not, push it into result.
- Result is returned.
function JsonToTree(arr) {
if (!Array.isArray(arr)) {
return arr;
}
let result = [];
let map = new Map(a);for (const item of arr) {
map.set(item.id, item);
}
for(const item of arr) {
if (map.get(item.parentId)) {
let parent = map.get(item.parentId);
parent.children = item;
map.set(item.parentId, parent);
}
else{ result.push(item); }}return result;
}
Copy the code
3 Scenario Problems
3.1 Circularly printing red, yellow and green
Problem: red 3s on once, green 1s on once, yellow 2s on once; How do I make three lights turn on again and again?
function flash(type, time) {
return new Promise((resolve, reject) = > {
setTimeout(() = > {
console.log(type);
resolve();
}, time);
});
}
function run() {
return flash('red'.3000)
.then(() = > flash('green'.1000))
.then(() = > flash('yellow'.2000))
.then(() = > run());
}
run();
Copy the code
3.2 Checking whether objects have circular references
Solution: Save recursive objects in a map and check if there is a circular reference.
function isCycle(obj, tem = {}) {
for(let o in obj) {
const v = obj[o];
if (typeof v === 'object') {
if (tem[v]) {
return true;
}
tem[v] = true;
if (isCycle(v, tem)) {
return true; }}}return false;
}
Copy the code