preface
Today is sunny, cloudy to clear, it is a good day to show their skills. Ding Ling ling, Xiao Wei45Degree Angle looked to the sky, the hair before the temples seems to be stubborn a few minutes. Small wei: "hello, who?" Interviewer: "Kunlun Mountain Mars sub-mountain group interviewer, saw your resume, quite can blow, very in line with our company temperament" Xiao Wei: "for a while?" Interviewer: "Bright Top!"Copy the code
play
1. Type judgment
Interviewer: How to determine exactly the type of variable? Xiao Wei: No problem
/ * * *@description Determine the data type *@param {*} variable
* @returns {string}* /
function getType(variable) {
return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
}
Copy the code
2. Anti-shake and throttling
Interviewer: How to understand the anti-shake and how to achieve it? Xiao Wei: did you play LOL? No matter how many times you press B to return to the city, it will be the last time to return after 8 seconds
/ * * *@description If you *@param {Function} fn
* @param {Number} t
* @returns * /
function debounce(fn, t) {
let timer = null;
return function() {
// Each call initializes the timer
timer && clearTimeout(timer);
timer = setTimeout(() = > {
fn.apply(this); }, t); }}Copy the code
Xiao Wei: Do you play fast music man? Do you experience the happiness of being chased by question marks? No matter how fast E presses, it still presses CD
/ * * *@description Throttling *@param {Function} fn
* @param {Number} t
* @returns * /
function throttle(fn, t) {
let timer = null;
return function() {
// Each call, if the timer exists, returns
if(timer) return;
fn.apply(this);
timer = setTimeout(() = > {
clearTimeout(timer);
timer = null; }, t); }}Copy the code
3, deep copy
Interviewer: Will it be a deep copy? Parse (json.stringify (obj)) interviewer: My broadsword is hungry… Xiao Wei: Put the knife down first
/ * * *@description Deep copy *@param {*} target
* @returns * /
function deepClone(target, cache = new WeakMap(a)) {
// The basic data type returns the original value directly
if(typeoftarget ! = ="Object") return target;
// Array objects distinguish initial values
const result = Array.isArray(target) ? [] : {};
// Map cache to avoid self-calls such as target.target = target that crash the program
if(cache.get(target)) return cache.get(target);
cache.set(target, result);
for(const k in target) {
result[k] = deepClone(target[k], cache);
}
return result;
}
Copy the code
4. Shuffle algorithm
Interviewer: once load officer, bah, realize a shuffle card algorithm (almost by this boy took partial) small wei: sexy load officer online deal card
/ * * *@description Shuffling *@param {Array} _arr
* @returns * /
function shuffle(_arr) {
let arr = _arr;
const newArr = [];
while (arr.length) {
const i = random(0, arr.length - 1);
newArr.push(arr[i]);
arr = arr.filter(j= >arr[i] ! == j); }return newArr;
}
Copy the code
5. Concurrent request restriction section
Interviewer: There are four toilets in guangming Ding, but now there are hundreds of students who need to go to the toilet, please solve it xiao Wei: You mean limit concurrency (serious face) Interviewer: The young man has two skills
Here are two ideas:1, divide the request list into n equal parts according to the maximum number of concurrent requests, use promise. All for each part, traverse n equal parts, and finally complete the execution callback. Disadvantages: If one of the requests is particularly slow, it will be obvious that the number of concurrent requests is1Instead of the maximum number of concurrent requests, which is obviously a waste of resources2, maintain a length of the maximum number of concurrent asynchronous queue, using recursion to solve the first direct start of the maximum number of concurrent requests, and then each completed one, then start another, so that can ensure that the request list is sufficient to maintain the maximum number of concurrent so, take the second method to achieve/ * * *@description Concurrent request limit *@param {Array} urlList
* @param {Number} maxNum
* @param {Function} callback
*/
function limitRequest(urlList, maxNum, callback) {
const resultMap = {}; // Result store
let currentIndex = 0; // The current request number
const handlerRequest = (url) = > {
console.log(`${url} - start`);
if(currentIndex < maxNum) { // If the number of requests does not reach the maximum number of concurrent requests, start the next request directly
currentIndex += 1;
handlerRequest(urlList[currentIndex]);
}
request(url).then(res= > {
// A request completed (successful)
console.log(`${url} - success end`);
resultMap[url] = res; // Collect results
currentIndex += 1;
// If there are more requests, proceed to the next one
if(urlList[currentIndex]) {
handlerRequest(urlList[currentIndex]);
}
// If the memory size is equal to the number of requests, all requests are processed and the callback is completed
if(Object.keys(resultMap).length >= urlList.length) {
callback && callback(resultMap);
}
}).catch(error= > {
// A request ends (failed), the same as success
console.log(`${url} - error end`);
resultMap[url] = error;
currentIndex += 1;
if(urlList[currentIndex]) {
handlerRequest(urlList[currentIndex]);
}
if(Object.keys(resultMap).length >= urlList.length) { callback && callback(resultMap); }}); }// Execute the first request manually
handlerRequest(urlList[0]);
}
/ * * *@description Random integer * between min Max@param {Number} min
* @param {Number} max
* @returns * /
function random(min, max) {
return min + Math.floor(Math.random()*(max + 1 - min));
}
/ * * *@description Mock request@param {String} url
* @returns * /
function request(url){
return new Promise((resolve, reject) = > {
setTimeout(() = > {
random(1.10) > 7 ? reject("error" + url) : resolve(url);
}, random(1.6) * 1000);
});
}
Copy the code
6. Array flattening
Interviewer: Implement an array flattening Xiao Wei: (pretending to think)
/ * * *@description Array flattening *@param {*} arr
* @returns * /
function flat(arr) {
let newArr = [];
for(const i of arr) {
if(Array.isArray(i)) {
// Array recursive values
newArr = [...newArr, ...flat(i)];
} else {
// Non-array push primitivesnewArr.push(i); }}return newArr;
}
Copy the code
Wei: (rolls his eyes and doesn’t want to speak)
/ * * *@description Array flattening reduce implementation *@param {*} arr
* @returns * /
function flatByReduce(arr) {
return arr.reduce((pre, cur) = > {
if(Array.isArray(cur)) {
return [...pre, ...cur];
}
returnpre.push(cur); } []); }Copy the code
7. Observer mode, publish – subscribe mode
Xiao Wei: (smoothing her hair above her eyes)
/ * * *@description Observer mode implementation */
// Target object
class Subject {
constructor() {
// Maintain a collection of observers
this.observerList = [];
}
// Add an observer
addObserver(observer) {
// Avoid adding observers repeatedly
if(this.observerList.includes(observer)) return;
this.observerList.push(observer);
}
// Delete the specified observer, not all deletion, high risk
removeObserver(observer) {
if(! observer)return;
this.observerList = this.observerList.filter(i= >i ! == observer); }// Notify the observer
notify() {
// If there is no observer, there is no knowledge
if(!this.observerList) return;
// Iterate over the update method that calls the observer
this.observerList.forEach(observer= > {
if(observer.update && Object.prototype.toString.call(observer.update).slice(8, -1) = = ="Function") { observer.update(); }}); }}/ / observer
class Observer {
update() {
console.log("I observed a change in the target."); }}Copy the code
Interviewer: What about publish-subscribe? Write down xiao wei :(frowns)
/ * * *@description Publish subscribe implementation */
class Event {
constructor() {
// Maintain an event object
this.eventHandler = {};
}
// Event subscription
on(key, fn) {
if(Object.prototype.toString.call(fn).slice(8, -1)! = ="Function") return;
// If not, create the event execution array
if(!this.eventHandler[key]) {
this.eventHandler[key] = [];
}
// Avoid repeated additions
if(this.eventHandler[key].includes(fn)) return;
this.eventHandler[key].push(fn);
}
// Event release
emit(key) {
if(!this.eventHandler[key] || !this.eventHandler[key].length) return;
this.eventHandler[key].forEach(fn= > fn());
}
// Unsubscribe
remove(key, fn) {
// Return if the event key is not passed
if(! key || !this.eventHandler[key]) return;
// Unsubscribe all subscriptions for the event if no specific method is passed
if(! fn) {this.eventHandler[key] = [];
return;
}
// Cancel a subscription for this event
this.eventHandler[key] = this.eventHandler[key].filter(i= > i !== fn);
}
}
Copy the code
Interviewer: Are there any similarities and differences between them? Xiao Wei: (😭) As for the two of them, in fact, the general idea is very similar, but the abstract dimension is slightly different.
The observer mode focuses on the relationship between the observer and the observed. The observed directly informs the observer to update the status, and there is no more concept of event key, which is relatively pure.
Publish-subscribe pattern is made by the publisher, subscribers, and event processing hub to form, personal understanding for release subscription through events hub building to complete decoupling between observation and observed, so that the function is more focused, only need to deal with the intermediate hubs, moreover also has the concept of event, release subscription can be different event to interact, And more flexible.
Of course, this is just my personal understanding, there are ten thousand Hamlets in ten thousand people’s hearts, the correct use of their own understanding, to solve the appropriate problem is the most crucial (personal views do not represent the public, cast the pot to protect safety 😂)
8. Responsive implementation of VUE
Interviewer: How does VUE implement data response xiao Wei: Data hijacking plus observer mode Interviewer: What hijacking method? Wei: I… Vue2 uses Object.defineProperty to hijack data, while VUe3 uses proxy
/ * * *@description Object.defineproperty implements responsive */
function defineReactive(data, key, value) {
Object.defineProperty(data, key, {
configurable: true.enumerable: true.set(newValue) {
console.log(Someone would `${key}Properties from${value}Changed to${newValue}`);
value = newValue;
},
get() {
console.log('Someone is reading${key}Attribute `);
returnvalue; }}); }function observer(data) {
for(const k indata) { defineReactive(data, k, data[k]); }}const data = {
name: "Xiao Ming".age: 24
}
observer(data);
data.age = 25;
console.log(data.age);
Copy the code
/ * * *@description Proxy implements reactive */
function observerByProxy(data) {
return new Proxy(data, {
get(target, key) {
console.log("get", target, key);
return target[key];
},
set(target, key, value) {
console.log("set", target, key, value); target[key] = value; }}); }const obj = observerByProxy({
name: "Xiao Ming".age: 24
});
obj.age = 25;
console.log(obj.age);
obj.father = "me";
obj.brother = "you";
console.log(obj.father);
console.log(obj.brother);
// Here xiao Wei connotation of a wave of Kunlun mountain interviewers, serious look to find, found in the comment area set 😂
Copy the code
Interviewer :(wf, smelly boy connotation I), say the difference between the two small wei :(😭 from the evil can not live). Object.defineproperty adds a set get method to all attribute values of the Object. However, because only existing attributes can be hijacked, responsivity cannot be realized for new attribute values of the Object in VUe2, only through vue. set processing can responsivity be achieved. But proxy is different, it is the whole object proxy, that is, whether the change of the value of the existing attribute or the new attribute can be perceived, that is, more awesome. However, proxy also has a big disadvantage, that is, proxy is only proposed by ES6, compatibility and defineProperty are not comparable, and many problems can not be solved through Poilyfill, only with sacrifice, the choice of the two is a trade-off.
Interviewer: (sucks, lets him do it) Ok, ok, what did vue.set do you just mentioned? Vue.set takes obj,key, and value, and basically checks whether the key property in OBJ is responsive that is, whether the key is an existing property, whether it’s an array property, etc., and if it’s not responsive, Use defineReactive to add a set Get method to make it responsible
Interviewer: For array operations, “arr[0] = 3” does not respond in vue. Why? XiaoWei: In fact, I have tried it myself. Arrays are similar to objects. DefineProperty can actually try to hijack arrays, but because arrays are uncontrollable, some of the performance waste caused by this is unexpected. Instead of using the array method mutation processing way elegant solution to the array problem
Interviewer :(not bad, but still high cold) well, ok, then we first here today, and then contact xiao wei :(swaying hair in the wind is no longer stubborn, but it does not mean that he does not have his own edge)
To be continued
conclusion
This story is pure fiction, any similarity is pure coincidence
Salute every front-end coder; The new one;