Note: the following contents are notes, which belong to the unformed article, please do not refer to
“Handwritten code”
Emulation implements deep copy
Core:
Shallow copy is a copy method referenced by shallow copy. Deep copy is a complete copy of an object. Copying here applies only to arrays and objects.
function shallowCopy(obj) {
// Base type returns
if (typeofobj ! = ='object' || obj === null) return obj;
let newObj = obj instanceof Array ? [] : {};
for (let key in obj) {
if(obj.hasOwnProperty(key)) { newObj[key] = obj[key]; }}return newObj;
}
function deepCopy(obj) {
// Base type returns
if (typeofobj ! = ='object' || obj === null) return obj;
let newObj = obj instanceof Array ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object'? deepCopy(obj[key]) : obj[key]; }}return newObj;
}
Copy the code
Achieve throttling and anti – shake
Image stabilization
The function is executed within n seconds of being fired, and then fired again within n seconds
- Search, which saves Ajax requests, also known as input field events, with shake-offs when the user keeps typing values
- Window triggers resize. Resize the browser window repeatedly to trigger resize. Use stabilization to make it trigger only once
function debounce(fn, delay, isImmediate) {
let timer = null;
return function () {
let context = this;
let args = arguments;
if (timer) clearTimeout(timer);
if (isImmediate) {
if(! timer) fn.apply(context, args) timer =setTimeout(function () {
timer = null;
}, delay);
} else {
timer = setTimeout(function () { fn.apply(context, args) }, delay); }}}Copy the code
The throttle
The function is executed only once at a time. If multiple fires occur during that time, the function is executed only once
- The mouse click event mousedown is triggered only once
function throttle(fn, delay) {
let base = 0;
let timer = null;
return function() {
let context = this;
let args = arguments;
let now = +new Date(a);let remain = delay - (now - base);
if(remain <= 0 || remain > delay) {
if(timer) {
clearTimeout(timer);
timer = null;
}
base = now;
fn.apply(context, args);
} else if(! timer) { timer =setTimeout(() = > {
base = +new Date(a); timer =null;
fn.apply(context, args);
}, remain)
}
}
}
Copy the code
Implement the function Currize
Transform a function that takes multiple arguments into a function that takes a single argument (the first argument of the original function), and return a new function that takes the remaining arguments and returns the result
const curry = (fn, ... args) = >
args.length < fn.length ? (.arguments) = >curry(fn, ... args, ... arguments) : fn(... args);// Test example
function sumFn(a, b, c) {
return a + b + c;
}
var sum = curry(sumFn);
console.log(sun(1) (2) (3));
console.log(sun(1) (2.3));
Copy the code
Application scenario: Parameter multiplexing. In essence, it is to reduce generality and improve applicability.
$. Ajax, $. Get, $. PostCopy the code
Implement array deduplication
function uniq(arr) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) === -1) { newArr.push(arr[i]); }}return newArr;
}
Copy the code
[...new Set(arr)];
Copy the code
Implement array flattening
function flat2(arr) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] instanceof Array) {
newArr = newArr.concat(flat2(arr[i]));
} else{ newArr.push(arr[i]); }}return newArr;
}
Copy the code
Implement array out of order
Core:
Fisher-yates: Iterates through a list of elements, and then swaps the current element with elements in a later random position
// abnormalSort
function shuffle(arr) {
for (let i = arr.length; i > 0; i--) {
let j = Math.floor(Math.random() * i);
[arr[i - 1], arr[j]] = [arr[j], arr[i - 1]];
}
return arr;
}
Copy the code
other
Implement an Observer to recursively bind all properties
function observer2(obj) {
return bindProperty(obj);
}
function bindProperty(obj) {
if(typeofobj ! = ='object' || obj === null) {
return
}
Object.keys(obj).forEach(key= > {
let value = obj[key];
if(typeofvalue ! = ='object') {
Object.defineProperty(obj, key, {
get() {
return value
},
set(newVal) {
console.log('set old value', value);
console.log('set new value', newVal); }})}else {
bindProperty(obj[key])
}
});
return obj;
}
let test = observer2({ b: 1.c: 3.d: { e: 3}}); test.b =2;
Copy the code
Analog implementation Promise
function myPromise(construtor) {
let self = this;
self.status = 'pending';
self.value = undefined;
self.error = undefined;
// Execute immediately after initialization
try {
construtor(resolve, rejected);
} catch(e) {
rejected(e);
}
function resolve(value) {
if(self.status === 'pending') {
self.status = 'resolved'; self.value = value; }}function rejected(error) {
if(self.status === 'pending') {
self.status = 'rejected';
self.error = error;
}
}
}
myPromise.prototype.then = (A, B) = > {
let self = this;
if(self.status === 'resolved') {
A(self.value);
}
if(self.status === 'rejected') { B(self.error); }}Copy the code
Implement compatible IE event monitoring
// Compatible with browsers
function bindEvent(obj, type, fn) {
if (obj.addEventListener) {
obj.addEventListener(type, eventFn);
} else {
obj.attachEvent("on" + type, eventFn);
}
function eventFn(e) {
const e = e || window.event;
consttarget = e.target || e.srcElemet; fn && fn(target, e); }}Copy the code
Handwritten XHR implementation
const req = new XMLHttpRequest();
req.open('GEt'.'/'.true);
req.onreadystatechange = () = > {
if(req.readyState === 4 && req.status === 200) {
console.log(res)
}
}
req.send();
Copy the code
Implementing event delegation
function trust(element, type, fn) {
element.addEventListener(type, e= > {
const current = e.target;
if(element.contains(current)) {
fn.call(current, e)
}
});
return element;
}
Copy the code
Implement trim function
var str = '324';
String.prototype.trim2 = function() {
return this.replace(/^\s\s*/.' ').replace(/\s\s*$/.' ');
}
str.trim2();
Copy the code
Add large numbers
function addStrs(str1, str2) {
let i = str1.length - 1, j = str2.length - 1, add = 0;
const arr = [];
while( i >= 0 || j >= 0|| add ! = =0) {
const x = parseInt(str1.charAt(i));
const y = parseInt(str1.charAt(i));
const res = x + y + add;
arr.push(res % 10);
add = Math.floor(res / 10);
i--, j--;
}
return arr.reverse().join(' ');
}
/ / test
var str1 = '13265456465', str2 = '26521132';
addStrs(str1, str2);
Copy the code
Implement drag-and-drop
// position: relative;
let dragging = false
let position = null
const xxx = document.querySelector('#xxx');
xxx.addEventListener('mousedown'.function(e) {
dragging = true
position = [e.clientX, e.clientY]
});
document.addEventListener('mousemove'.function(e) {
if(dragging === false) return null
const x = e.clientX
const y = e.clientY
const deltaX = x - position[0]
const deltaY = y - position[1]
const left = parseInt(xxx.style.left || 0)
const top = parseInt(xxx.style.top || 0)
xxx.style.left = left + deltaX + 'px'
xxx.style.top = top + deltaY + 'px'
position = [x, y]
});
document.addEventListener('mouseup'.function(e){
dragging = false
});
Copy the code
Implement the Event class, on off emit
class Event {
constructor () {
// Store the event data structure
// For quick lookups, use objects (dictionaries)
this._cache = {}
}
/ / binding
on(type, callback) {
// For convenience and space saving
// Place events of the same type in an array
// The array is a queue, followed by first-in, first-out
// The newly bound event is emitted first
let fns = (this._cache[type] = this._cache[type] || [])
if(fns.indexOf(callback) === -1) {
fns.push(callback)
}
return this
}
/ / triggers
// emit
trigger(type, data) {
let fns = this._cache[type]
if(Array.isArray(fns)) {
fns.forEach((fn) = > {
fn(data)
})
}
return this
}
/ / unbundling
off (type, callback) {
let fns = this._cache[type]
if(Array.isArray(fns)) {
if(callback) {
let index = fns.indexOf(callback)
if(index ! = = -1) {
fns.splice(index, 1)}}else {
// Empty all
fns.length = 0}}return this}}Copy the code
Realize the getValue
function deepGet(obj, keys, defaultVal) {
return((!Array.isArray(keys)
? keys.replace(/\[/g.'. ').replace(/\]/g.' ').split('. ')
: keys
).reduce((o, k) = > (o || {})[k], obj) || defaultVal
);
}
// Test example
var obj = {
a: [{b: {
c: 3,}},],e: {
f: 1,}};console.log(deepGet(obj, 'e.f')); / / 1
console.log(deepGet(obj, ['e'.'f'])) / / 1
console.log(deepGet(obj, 'a.x')); // undefined
console.log(deepGet(obj, 'a.x'.The '-')) // --
console.log(deepGet(obj, 'a[0].b.c')) / / 3
console.log(deepGet(obj, ['a'.0.'b'.'c'])) / / 3
Copy the code
reference
- Here are 20 big factory interview questions for you to check
“Data structure”
Arrays and linked lists
The stack and queue
The tree
Ordinary binary tree, balanced binary tree, complete binary tree, binary search tree
The convenience of binary trees
“Algorithm”
Sorting algorithm
The bubbling
Time complexity O(n*n)
- Compare adjacent elements, and if the former is larger than the latter, they swap places. Cycle operation
- Remove the last element and repeat for the rest
function bubbleSort(arr) {
const len = arr.length;
for(let i = 0; i < len - 1; i++) {
for(let j = 0; j < len - 1 -i; j++) {
if(arr[j] > arr[j+1]) {
[arr[j], arr[j+1]] = [arr[j+1], arr[j]]
}
}
}
return arr;
}
Copy the code
fast
Time complexity: O(nlogn)
- Take the middle number as the base, prepare two array containers, and compare the remaining elements against the base one by one, placing the smaller ones in the left container and the larger ones in the right container
- The elements of the two containers are recursively processed and the processed data and cardinality are combined into an array by size
function quickSort(arr) {
let len = arr.length;
if(len <= 1) {
return arr;
}
let index = Math.floor(len / 2);
let middle = arr.splice(index, 1);
let left = [], right = [];
for(let i = 0; i < arr.length; i++) {
if(arr[i] < middle[0]) {
left.push(arr[i]);
} else{ right.push(arr[i]); }}return quickSort(left).concat(middle, quickSort(right));
}
Copy the code
insert
Time complexity: O(n*n)
- Starting with the first element, the element can be considered sorted;
- Fetch the next element and scan back to front in the sorted element sequence;
- If the element (sorted) is larger than the new element, move the element to the next position;
- Repeat step 3 until you find a place where the sorted element is less than or equal to the new element;
function insertSort(arr) {
for(let i = 0; i < arr.length; i++) {
let preIndex = i - 1,
cur = arr[i];
while(preIndex >= 0 && arr[preIndex] > cur) {
arr[preIndex + 1] = arr[preIndex];
preIndex--;
}
arr[preIndex + 1] = cur;
}
return arr;
}
Copy the code
choose
Time complexity O(n*n)
The largest (smallest) element of the array to be sorted is selected as the first element at a time until the array is sorted
function selectSort(arr) {
let len = arr.length, temp = 0;
for(let i = 0; i < len; i++) {
temp = i;
for(let j = i + 1; j < len; j++) {
if(arr[j] < arr[temp]) { temp = j; }}if(temp ! == i) { [arr[i], arr[temp]] = [arr[temp], arr[i]]; }returnarr; }}Copy the code
Dynamic programming
Search algorithm
Depth-first search algorithm
(DFS for short)
Breadth-first search algorithm
(BFS for short)