1. If you
function debounce(func, ms = 1000) {
let timer;
return function (. args) {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() = > {
func.apply(this, args)
}, ms)
}
}
/ / test
const task = () = > { console.log('run task')}const debounceTask = debounce(task, 1000)
window.addEventListener('scroll', debounceTask)
Copy the code
2. The throttle
function throttle(func, ms = 1000) {
let canRun = true
return function (. args) {
if(! canRun)return
canRun = false
setTimeout(() = > {
func.apply(this, args)
canRun = true
}, ms)
}
}
/ / test
const task = () = > { console.log('run task')}const throttleTask = throttle(task, 1000)
window.addEventListener('scroll', throttleTask)
Copy the code
3. new
function myNew(Func, ... args) {
const instance = {};
if (Func.prototype) {
Object.setPrototypeOf(instance, Func.prototype)
}
const res = Func.apply(instance, args)
if (typeof res === "function"| | -typeof res === "object"&& res ! = =null)) {
return res
}
return instance
}
/ / test
function Person(name) {
this.name = name
}
Person.prototype.sayName = function() {
console.log(`My name is The ${this.name}`)}const me = myNew(Person, 'Jack')
me.sayName()
console.log(me)
Copy the code
4. bind
Function.prototype.myBind = function (context = globalThis) {
const fn = this
const args = Array.from(arguments).slice(1)
const newFunc = function () {
constnewArgs = args.concat(... arguments)if (this instanceof newFunc) {
// Bind this to the instance object with the new call
fn.apply(this, newArgs)
} else {
// Bind the context by calling it as a normal function
fn.apply(context, newArgs)
}
}
// New calls are supported
newFunc.prototype = Object.create(fn.prototype)
return newFunc
}
/ / test
const me = { name: 'Jack' }
const other = { name: 'Jackson' }
function say() {
console.log(`My name is The ${this.name || 'default'}`);
}
const meSay = say.myBind(me)
meSay()
const otherSay = say.myBind(other)
otherSay()
Copy the code
5. call
Function.prototype.myCall = function (context = globalThis) {
// The key step is to call the method on the context, trigger this binding as context, and use Symbol to prevent overwriting the original property
const key = Symbol('key')
context[key] = this
// Es5 can get an array of arguments by iterating for
const args = [...arguments].slice(1)
constres = context[key](... args)delete context[key]
return res
};
/ / test
const me = { name: 'Jack' }
function say() {
console.log(`My name is The ${this.name || 'default'}`);
}
say.myCall(me)
Copy the code
6. apply
Function.prototype.myApply = function (context = globalThis) {
// The key step is to call the method on the context, trigger this binding as context, and use Symbol to prevent overwriting the original property
const key = Symbol('key')
context[key] = this
let res
if (arguments[1]) { res = context[key](... arguments[1])}else {
res = context[key]()
}
delete context[key]
return res
}
/ / test
const me = { name: 'Jack' }
function say() {
console.log(`My name is The ${this.name || 'default'}`);
}
say.myApply(me)
Copy the code
7. deepCopy
function deepCopy(obj, cache = new WeakMap(a)) {
if(! objinstanceof Object) return obj
// Prevent circular references
if (cache.get(obj)) return cache.get(obj)
// Support functions
if (obj instanceof Function) {
return function () {
return obj.apply(this.arguments)}}// Support date
if (obj instanceof Date) return new Date(obj)
// Regular objects are supported
if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags)
// You can also add other objects, such as: Map, Set, etc
// Array is a special object whose key is numeric element silver
const res = Array.isArray(obj) ? [] : {}
// Cache the copy object to handle cyclic references
cache.set(obj, res)
Object.keys(obj).forEach((key) = > {
if (obj[key] instanceof Object) {
res[key] = deepCopy(obj[key], cache)
} else {
res[key] = obj[key]
}
});
return res
}
/ / test
const source = {
name: 'Jack'.meta: {
age: 12.birth: new Date('1997-10-10'),
ary: [1.2, { a: 1}].say() {
console.log('Hello');
}
}
}
source.source = source
const newObj = deepCopy(source)
console.log(newObj.meta.ary[2] === source.meta.ary[2]); // false
console.log(newObj.meta.birth === source.meta.birth); // false
Copy the code
8. Event bus | published a subscription model
class EventEmitter {
constructor() {
this.cache = {}
}
on(name, fn) {
if (this.cache[name]) {
this.cache[name].push(fn)
} else {
this.cache[name] = [fn]
}
}
off(name, fn) {
const tasks = this.cache[name]
if (tasks) {
const index = tasks.findIndex((f) = > f === fn || f.callback === fn)
if (index >= 0) {
tasks.splice(index, 1)}}}emit(name) {
if (this.cache[name]) {
// Create a copy. If the same event continues to be registered within the callback function, an infinite loop will occur
const tasks = this.cache[name].slice()
for (let fn oftasks) { fn(); }}}emit(name, once = false) {
if (this.cache[name]) {
// Create a copy. If the same event continues to be registered within the callback function, an infinite loop will occur
const tasks = this.cache[name].slice()
for (let fn of tasks) {
fn();
}
if (once) {
delete this.cache[name]
}
}
}
}
/ / test
const eventBus = new EventEmitter()
const task1 = () = > { console.log('task1'); }
const task2 = () = > { console.log('task2'); }
eventBus.on('task', task1)
eventBus.on('task', task2)
setTimeout(() = > {
eventBus.emit('task')},1000)
Copy the code
9. Corrification: Call a function with only a few arguments and let it return a function to process the rest
function curry(func) {
return function curried(. args) {
Function. length is used to obtain the number of parameters of a function
// Supplement: arguments.length gets the number of arguments
if (args.length >= func.length) {
return func.apply(this, args)
}
return function (. args2) {
return curried.apply(this, args.concat(args2))
}
}
}
/ / test
function sum (a, b, c) {
return a + b + c
}
const curriedSum = curry(sum)
console.log(curriedSum(1.2.3))
console.log(curriedSum(1) (2.3))
console.log(curriedSum(1) (2) (3))
Copy the code
10. Es5 implements inheritance
function create(proto) {
function F() {}
F.prototype = proto;
return new F();
}
// Parent
function Parent(name) {
this.name = name
}
Parent.prototype.sayName = function () {
console.log(this.name)
};
// Child
function Child(age, name) {
Parent.call(this, name)
this.age = age
}
Child.prototype = create(Parent.prototype)
Child.prototype.constructor = Child
Child.prototype.sayAge = function () {
console.log(this.age)
}
/ / test
const child = new Child(18.'Jack')
child.sayName()
child.sayAge()
Copy the code
11. instanceof
function isInstanceOf(instance, klass) {
let proto = instance.__proto__
let prototype = klass.prototype
while (true) {
if (proto === null) return false
if (proto === prototype) return true
proto = proto.__proto__
}
}
/ / test
class Parent {}
class Child extends Parent {}
const child = new Child()
console.log(isInstanceOf(child, Parent), isInstanceOf(child, Child), isInstanceOf(child, Array));
Copy the code
12. Limit on the number of asynchronous concurrent requests
/** * key * 1. New promise will be executed immediately after it is created * 2. Use promise.resolve ().then to add tasks to the microtask queue, preventing immediate execution of the iterative method * 3. In the process of microtask processing, new microtasks will be added to the microtask queue within the same event cycle. Use race to continue adding tasks when a task is complete, keeping the task running at the maximum number of concurrent tasks * 5. When the task is complete, it needs to be removed from doingTasks */
function limit(count, array, iterateFunc) {
const tasks = []
const doingTasks = []
let i = 0
const enqueue = () = > {
if (i === array.length) {
return Promise.resolve()
}
const task = Promise.resolve().then(() = > iterateFunc(array[i++]))
tasks.push(task)
const doing = task.then(() = > doingTasks.splice(doingTasks.indexOf(doing), 1))
doingTasks.push(doing)
const res = doingTasks.length >= count ? Promise.race(doingTasks) : Promise.resolve()
return res.then(enqueue)
};
return enqueue().then(() = > Promise.all(tasks))
}
// test
const timeout = i= > new Promise(resolve= > setTimeout(() = > resolve(i), i))
limit(2[1000.1000.1000.1000], timeout).then((res) = > {
console.log(res)
})
Copy the code
13. Asynchronous serial asynchronous parallel |
// byte interview questions, implement an asynchronous addition
function asyncAdd(a, b, callback) {
setTimeout(function () {
callback(null, a + b);
}, 500);
}
// Solution
// 1. promisify
const promiseAdd = (a, b) = > new Promise((resolve, reject) = > {
asyncAdd(a, b, (err, res) = > {
if (err) {
reject(err)
} else {
resolve(res)
}
})
})
// 2. Serial processing
async function serialSum(. args) {
return args.reduce((task, now) = > task.then(res= > promiseAdd(res, now)), Promise.resolve(0))}// 3. Parallel processing
async function parallelSum(. args) {
if (args.length === 1) return args[0]
const tasks = []
for (let i = 0; i < args.length; i += 2) {
tasks.push(promiseAdd(args[i], args[i + 1] | |0))}const results = await Promise.all(tasks)
returnparallelSum(... results) }/ / test
(async() = > {console.log('Running... ');
const res1 = await serialSum(1.2.3.4.5.8.9.10.11.12)
console.log(res1)
const res2 = await parallelSum(1.2.3.4.5.8.9.10.11.12)
console.log(res2)
console.log('Done'); }) ()Copy the code
14. vue reactive
// Dep module
class Dep {
static stack = []
static target = null
deps = null
constructor() {
this.deps = new Set()}depend() {
if (Dep.target) {
this.deps.add(Dep.target)
}
}
notify() {
this.deps.forEach(w= > w.update())
}
static pushTarget(t) {
if (this.target) {
this.stack.push(this.target)
}
this.target = t
}
static popTarget() {
this.target = this.stack.pop()
}
}
// reactive
function reactive(o) {
if (o && typeof o === 'object') {
Object.keys(o).forEach(k= > {
defineReactive(o, k, o[k])
})
}
return o
}
function defineReactive(obj, k, val) {
let dep = new Dep()
Object.defineProperty(obj, k, {
get() {
dep.depend()
return val
},
set(newVal) {
val = newVal
dep.notify()
}
})
if (val && typeof val === 'object') {
reactive(val)
}
}
// watcher
class Watcher {
constructor(effect) {
this.effect = effect
this.update()
}
update() {
Dep.pushTarget(this)
this.value = this.effect()
Dep.popTarget()
return this.value
}
}
// Test the code
const data = reactive({
msg: 'aaa'
})
new Watcher(() = > {
console.log('===> effect', data.msg);
})
setTimeout(() = > {
data.msg = 'hello'
}, 1000)
Copy the code
15. promise
/ / suggested reading Promises/A + standard (https://promisesaplus.com/)
class MyPromise {
constructor(func) {
this.status = 'pending'
this.value = null
this.resolvedTasks = []
this.rejectedTasks = []
this._resolve = this._resolve.bind(this)
this._reject = this._reject.bind(this)
try {
func(this._resolve, this._reject)
} catch (error) {
this._reject(error)
}
}
_resolve(value) {
setTimeout(() = > {
this.status = 'fulfilled'
this.value = value
this.resolvedTasks.forEach(t= > t(value))
})
}
_reject(reason) {
setTimeout(() = > {
this.status = 'reject'
this.value = reason
this.rejectedTasks.forEach(t= > t(reason))
})
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) = > {
this.resolvedTasks.push((value) = > {
try {
const res = onFulfilled(value)
if (res instanceof MyPromise) {
res.then(resolve, reject)
} else {
resolve(res)
}
} catch (error) {
reject(error)
}
})
this.rejectedTasks.push((value) = > {
try {
const res = onRejected(value)
if (res instanceof MyPromise) {
res.then(resolve, reject)
} else {
reject(res)
}
} catch (error) {
reject(error)
}
})
})
}
catch(onRejected) {
return this.then(null, onRejected); }}/ / test
new MyPromise((resolve) = > {
setTimeout(() = > {
resolve(1);
}, 500);
}).then((res) = > {
console.log(res);
return new MyPromise((resolve) = > {
setTimeout(() = > {
resolve(2);
}, 500);
});
}).then((res) = > {
console.log(res);
throw new Error('a error')
}).catch((err) = > {
console.log('= = >', err);
})
Copy the code
16. Array flattening
/ / plan 1
function recursionFlat(ary = []) {
const res = []
ary.forEach(item= > {
if (Array.isArray(item)) { res.push(... recursionFlat(item)) }else {
res.push(item)
}
})
return res
}
2 / / solution
function reduceFlat(ary = []) {
return ary.reduce((res, item) = > res.concat(Array.isArray(item) ? reduceFlat(item) : item), [])
}
/ / test
const source = [1.2[3.4[5.6]], '7']
console.log(recursionFlat(source))
console.log(reduceFlat(source))
Copy the code
17. Object flattening
function objectFlat(obj = {}) {
const res = {}
function flat(item, preKey = ' ') {
Object.entries(item).forEach(([key, val]) = > {
const newKey = preKey ? `${preKey}.${key}` : key
if (val && typeof val === 'object') {
flat(val, newKey)
} else {
res[newKey] = val
}
})
}
flat(obj)
return res
}
/ / test
const source = { a: { b: { c: 1.d: 2 }, e: 3 }, f: { g: 2}}console.log(objectFlat(source));
Copy the code
18. Lazy loading of images
// <img src="default.png" data-src="https://xxxx/real.png">
function isVisible(el) {
const position = el.getBoundingClientRect()
const windowHeight = document.documentElement.clientHeight
// The top edge is visible
const topVisible = position.top > 0 && position.top < windowHeight;
// The bottom edge is visible
const bottomVisible = position.bottom < windowHeight && position.bottom > 0;
return topVisible || bottomVisible;
}
function imageLazyLoad() {
const images = document.querySelectorAll('img')
for (let img of images) {
const realSrc = img.dataset.src
if(! realSrc)continue
if (isVisible(img)) {
img.src = realSrc
img.dataset.src = ' '}}}/ / test
window.addEventListener('load', imageLazyLoad)
window.addEventListener('scroll', imageLazyLoad)
// or
window.addEventListener('scroll', throttle(imageLazyLoad, 1000))
Copy the code
Welcome to add ~ Github address
Summarizes the intention of a recent article system to front end of the interview, this paper deliberately did not specify a lot of the knowledge of the specific details, but on the whole analysis of the each link of the interview has everything to do with the key, hope to be able to give the interview a novice some guidance, but because of “I don’t understand”, this article has been unable to recommend, so far, no one can see, If you are interested, you can click on it. I think this article can be used as an action guide for interview novices, and I hope it can help people in need.