前端面试出场率奇高的18个手写代码

}

// 测试 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]);

8. 事件总线 | 发布订阅模式

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]) {

// 创建副本,如果回调函数内继续注册相同事件,会造成死循环 const tasks = this.cache[name].slice()

for (let fn of tasks) {

fn();

}

}

}

emit(name, once = false) {

if (this.cache[name]) {

// 创建副本,如果回调函数内继续注册相同事件,会造成死循环 const tasks = this.cache[name].slice()

for (let fn of tasks) {

fn();

}

if (once) {

delete this.cache[name]

}

}

}

}

// 测试 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)

9. 柯里化:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数

function curry(func) {

return function curried(…args) {

// 关键知识点:function.length 用来获取函数的形参个数 // 补充:arguments.length 获取的是实参个数 if (args.length >= func.length) {

return func.apply(this, args)

}

return function (…args2) {

return curried.apply(this, args.concat(args2))

}

}

}

// 测试 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))

10. es5 实现继承

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)

}

// 测试 const child = new Child(18, ‘Jack’)

child.sayName()

child.sayAge()

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

}

}

// 测试 class Parent {}

class Child extends Parent {}

const child = new Child()

console.log(isInstanceOf(child, Parent), isInstanceOf(child, Child), isInstanceOf(child, Array))

12. 异步并发数限制

/**

  • 关键点 * 1. new promise 一经创建,立即执行 * 2. 使用 Promise.resolve().then 可以把任务加到微任务队列,防止立即执行迭代方法 * 3. 微任务处理过程中,产生的新的微任务,会在同一事件循环内,追加到微任务队列里 * 4. 使用 race 在某个任务完成时,继续添加任务,保持任务按照最大并发数进行执行 * 5. 任务完成后,需要从 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)

})

13. 异步串行 | 异步并行

// 字节面试题,实现一个异步加法 function asyncAdd(a, b, callback) {

setTimeout(function () {

callback(null, a + b);

}, 500);

}

// 解决方案 // 1. promisify const promiseAdd = (a, b) => new Promise((resolve, reject) => {

asyncAdd(a, b, (err, res) => {

if (err) {

reject(err)

} else {

resolve(res)

}

})

})

// 2. 串行处理 async function serialSum(…args) {

return args.reduce((task, now) => task.then(res => promiseAdd(res, now)), Promise.resolve(0))

}

// 3. 并行处理 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)

return parallelSum(…results)

}

// 测试 (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’);

})()

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

}

}

// 测试代码 const data = reactive({

msg: ‘aaa’

})

new Watcher(() => {

console.log(‘===> effect’, data.msg);

})

setTimeout(() => {

data.msg = ‘hello’

}, 1000)

15. promise

// 建议阅读 Promises/A+ 标准 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);

}

}

// 测试 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);

})

16.数组扁平化

// 方案 1 function recursionFlat(ary = []) {

const res = []

ary.forEach(item => {

if (Array.isArray(item)) {

res.push(…recursionFlat(item))

} else {

res.push(item)

}

})

return res

}

// 方案 2 function reduceFlat(ary = []) {

return ary.reduce((res, item) => res.concat(Array.isArray(item) ? reduceFlat(item) : item), [])

}

// 测试 const source = [1, 2, [3, 4, [5, 6]], ‘7’]

console.log(recursionFlat(source))

console.log(reduceFlat(source))

17. 对象扁平化

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
.reduce((res, item) => res.concat(Array.isArray(item) ? reduceFlat(item) : item), [])

}

// 测试 const source = [1, 2, [3, 4, [5, 6]], ‘7’]

console.log(recursionFlat(source))

console.log(reduceFlat(source))

17. 对象扁平化

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-rIkeDC1W-1715893853068)]

[外链图片转存中…(img-X6LmpQdy-1715893853069)]

[外链图片转存中…(img-B8rcIUwx-1715893853069)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值