前端面试手写代码

小小杨 2021-10-13 11:20:03
面试 前端 端面 手写 试手


单例模式

class SingleObject{
constructor(name) {
this.name = name
}
login() {
console.log('name: ', this.name)
}
}
SingleObject.getInstance = (() => {
let instance
return (name) => {
if (!instance) {
instance = new SingleObject(name)
}
return instance
}
})()
// 测试
const a = SingleObject.getInstance('yang')
const b = SingleObject.getInstance('guo')
console.log(a === b) // true
console.log(a.login(), b.login()) // yang
// getInstance是类的静态方法,不能使用new SingleObject()
// 创建出来的实例全等

观察者模式

// 目标对象
class Subject{
constructor() {
this.subs = []
}
addSub(sub) {
this.subs.push(sub)
}
notify() {
this.subs.map(sub => {
sub.update()
})
}
}
// 观察者
class Observer{
update() {
console.log('updating')
}
}
// 测试
const subject = new Subject()
const observer = new Observer()
subject.addSub(observer)
subject.notify()
// 首先是目标的构造函数,他有个数组,用于添加观察者
// 还有个广播方法notify,遍历观察者数组后调用观察者们的update方法

发布订阅模式

class EventEmitter{
constructor() {
this._eventPool = {}
}
on(event, cb) {
this._eventPool.event ?
this._eventPool.event.push(cb)
:
this._eventPool[event] = [cb]
}
off(event) {
delete this._eventPool[event]
}
emit(event, ...args) {
if (this._eventPool[event]) {
this._eventPool[event].map(cb => {
cb(...args)
})
}
}
once(event, cb) {
this.on(event, (...args) => {
cb(...args)
this.off(event)
})
}
}
// 测试
const emitter = new EventEmitter()
emitter.on('a', (aaa, bbb) => {
console.log('fffffff', aaa, bbb)
})
emitter.emit('a', 'windy', 'tom')
emitter.once('b', (aaa, bbb) => {
console.log('fffffff', aaa, bbb)
})
emitter.emit('b', 'windy', 'tom')

基于一个主题/事件通道,订阅者subscriber通过自定义事件订阅主题,发布者publisher通过发布主题事件的方式发布。

观察者模式和发布订阅模式区别

  1. 在观察者模式中,观察者需要直接订阅目标事件。在目标发出内容改变的事件后,直接接收事件并作出响应。
  2. 发布订阅模式相比观察者模式多了个主题/事件通道,订阅者和发布者不是直接关联的。
  3. 观察者模式两个对象之间有很强的依赖关系;发布/订阅模式两个对象之间的耦合度低。

函数柯里化

当我们没有重新定义toString与valueOf时,函数的隐式转换会调用默认的toString方法,它会将函数的定义内容作为字符串返回。

而当我们主动定义了toString/vauleOf方法时,那么隐式转换的返回结果则由我们自己控制了。其中valueOf的优先级会toString高一点。

柯里化好处:参数复用、延迟运行(返回函数,想什么时候运行什么时候运行)

function currying() {
const [fn, ..._args] = [...arguments]
const cb = function() {
if (!arguments.length) {
return fn.apply(this, _args)
}
_args.push(...arguments)
return cb
}
// 可根据需要添加
cb.toString = fn.apply(this, _args)
return cb
}
// 测试柯里化
function add() {
return [...arguments].reduce((a, b) => a + b)
}
const a = currying(add, 12, 24, 36)
console.log(a()) // 72

实现一个add方法,使结果满足如下预期


add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;
function add() {
let _args = [...arguments]
const _adder = function() {
_args.push(...arguments)
return _adder
}
_adder.toString = function() {
return _adder.reduce((a, b) => a + b)
}
return _adder
}

实现call和apply


Function.prototype.myCall = function() {
let [context, ...args] = [...arguments]
if (!context) context = window
context.fn = this
const res = context.fn(...args)
delete context.fn
return res
}
Function.prototype.myApply = function() {
let [context, args] = [...arguments]
if (!context) context = window
context.fn = this
let res
if (args) {
res = context.fn(...args)
} else {
res = context.fn()
}
delete context.fn
return res
}
// 测试
const person = {
name: 'mike',
getName: function(a, b) {
console.log(this.name, a, b)
}
}
function printName(a, b) {
console.log(this.name, a, b)
}
printName.myCall(person, 'time', 'fly')
printName.myApply(person, ['time', 'fly'])

实现bind

Function.prototype.myBind = function() {
const [context, ...args] = [...arguments]
const _this = this
return function() {
return _this.apply(context, args.concat(...arguments))
}
}
const person = {
name: 'mike',
getName: function(a, b) {
console.log(this.name, a, b)
}
}
// 测试
const boy = {
name: 'boy'
}
const getName2 = person.getName.myBind(boy, 'hhhh', 'yyyy')
getName2() // boy hhhh yyyy

实现instanceof

function myInstanceof(left, right) {
let leftVal = left.__proto__
let rightVal = right.prototype
while (true) {
if (leftVal === null) return false
if (leftVal === rightVal) return true
leftVal = leftVal.__proto__
}
}

new的本质

function myNew(fun) {
return function() {
const obj = {
__proto__: fun.prototype
}
fun.call(obj, ...arguments)
return obj
}
}
// 测试
function Person(name, age) {
this.name = name
this.age = age
}
const obj = myNew(Person)('yang', 18)
// Person { name: 'yang', age: 18 }

Object.create的基本原理

function myCreate(obj) {
function F() {}
F.prototype = obj
return new F()
}

实现promise

class MyPromise{
constructor(process) {
this.status = 'pending'
this.msg = ''
process(this.resolve.bind(this), this.reject.bind(this))
return this
}
resolve(val) {
this.status = 'fulfilled'
this.msg = val
}
reject(val) {
this.status = 'rejected'
this.msg = val
}
then(fulfilled, reject) {
if (this.status === 'fulfilled') {
fulfilled(this.msg)
}
if (this.status === 'rejected'){
reject(this.msg)
}
}
}
// 测试
const mm = new MyPromise((resolve, reject) => {
resolve('123')
})
mm.then(res => {
console.log(res, 'success')
})

防抖和节流

所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。

区别:

  1. 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。
  2. 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。

应用:进行窗口的resize、scroll,输入框内容校验或请求ajax时

// 防抖
function debounce(fn, time) {
let timeout
return function() {
const _this = this
const args = arguments
if (timeout) clearTimeout(timeout)
timeout = setTimeout(() => {
fn.apply(_this, args)
}, time || 500)
}
}
// 节流
function throttle(fn, time) {
let timeout
return function() {
const _this = this
const args = arguments
if (!timeout) {
timeout = setTimeout(() => {
fn.apply(_this, args)
timeout = null
}, time || 500)
}
}
}
function count() {
console.log('counting')
}
window.onscroll = debounce(count, 1000)
window.onscroll = throttle(count, 1000)

for循环和reduce实现map和filter

// for循环实现map
Array.prototype.map2 = function() {
const arr = this
const [fn, thisArg] = [...arguments]
let res = []
for ( let i = 0; i < arr.length; i++) {
res.push(fn.call(thisArg, arr[i], i, arr))
}
return res
}
// reduce实现map
Array.prototype.map3 = function() {
const arr = this
const [fn, thisArg] = [...arguments]
return arr.reduce((acc, cur, i) => {
acc.push(fn.call(thisArg, cur, i, arr))
return acc
}, [])
}
// 测试map
const m = [1,2,3,4,54].map2(item => item * item)
console.log(m) // [ 1, 4, 9, 16, 2916 ]
// for循环实现filter
Array.prototype.filter2 = function() {
const arr = this
const [fn, thisArg] = [...arguments]
let res = []
for ( let i = 0; i < arr.length; i++) {
if (fn.call(thisArg, arr[i], i, arr)) {
res.push(arr[i])
}
}
return res
}
// reduce实现filter
Array.prototype.filter3 = function() {
const arr = this
const [fn, thisArg] = [...arguments]
return arr.reduce((acc, cur, i) => {
fn.call(thisArg, cur, i, arr) && acc.push(cur)
return acc
}, [])
}
// 测试filter
const n = [0, 1, 2, 3, 4, 5]
const n2 = n.filter3(item => item % 2)
console.log(n2) // [ 1, 3, 5 ]

使用for循环打印1-10, 每个数字出现间隔500ms

错误方法:

// 结果虽然依次输出了1-10,但是每个数字之间没有间隔,是一次性输出的,所以不正确
for (var i = 1; i <= 10; i++) {
setTimeout((function(i) {
console.log(i);
})(i), 500);
}

正确方法:


// 使用闭包,注意setTimeout, 每隔500ms,因此每次传递的间隔时间要乘以i
for(var i=1;i<=10;i++){
(function(i){
setTimeout(function(){
console.log(i);
},500 * i);
})(i);
}

或者使用let,let本身就是块级作用域

for(let i=1;i<=10;i++){
setTimeout(function(){
console.log(i);
},500 * i);
}

使用setTimeout模拟setInterval


function fn() {
console.log('123')
}
setTimeout(function f() {
fn()
setTimeout(f, 500)
}, 500)

ES5实现继承

function Parent() {
this.name = 'parent'
this.play = [1, 2, 3]
}
function Child() {
Parent.call(this)
this.name = 'child'
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
// 测试
const ss = new Child()
console.log(ss instanceof Child, ss instanceof Parent) // true true
console.log(ss.constructor) // Child

本文分享自微信公众号 - 下落木(yanggwcn)

原文出处及转载信息见文内详细说明,如有侵权,请联系 [email protected] 删除。

原始发表时间: 2020-06-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

版权声明
本文为[小小杨]所创,转载请带上原文链接,感谢
https://cloud.tencent.com/developer/article/1888083

  1. Nodejs + Serverless实现LaTeX公式渲染服务
  2. Analyse des questions d'entrevue: déstockage des tableaux et complexité temporelle
  3. Flux de données pour l'analyse des sources de vue
  4. Take group photos, sing songs and write blessings... Everyone on the Fuxing train celebrates the national day
  5. React核心 -- React-Hooks
  6. Mise en œuvre du Service de rendu de formule latex par nodejs + serverless
  7. React Core - React Hooks
  8. After autumn, wear less black, white and gray, and choose more gentle "light colors"
  9. Wu Qili sent blessings on the national day. She looked haggard and thin on her own. It was worrying
  10. Grand sens de la vue à la fois, la force dure est excellente, toute la série 2.0t, le film réel 2021 haver h9!
  11. With the blessing of Toyota power, GAC motor's new gs8 is open for pre-sale, starting from 188800 yuan
  12. Test drive Xingyue L: the price is less than 200000, but there are 400000 cards. Is it inevitable to sell more than 10000 a month?
  13. Entrevue de première ligne 3 + 1 tous les jours - jour 909
  14. Entrevue de première ligne 3 + 1 par jour - jour 910
  15. Xiao Zhan's 18 word blessing copy triggered a heated discussion, and fans expressed their attitude and wished the motherland together
  16. Engineering Knowledge Card 005: comment webpack injecte - t - il les ressources JS emballées dans html?
  17. ant design vue 设置表格选择框,全选按钮选不全
  18. 五分钟掌握用Vue脚手架搭建一个完整项目!
  19. 100 questions d'entrevue Python de base partie 2 (41 - 60)
  20. 五分鐘掌握用Vue脚手架搭建一個完整項目!
  21. ant design vue 設置錶格選擇框,全選按鈕選不全
  22. Cinq minutes pour construire un projet complet avec l'échafaudage vue!
  23. La vue de conception ant définit la zone de sélection de la table, le bouton sélectionner tout n'est pas sélectionné
  24. vuex中助手函数的几种使用技巧总结
  25. La nouvelle voiture roule à grande vitesse, le tableau de bord apparaît "tasse de café" prompt, directement au magasin 4S!
  26. Résumé de plusieurs techniques d'utilisation de la fonction Helper dans vuex
  27. Un disciple féminin est venu à guozijian: Zhuo Wenyuan a été complètement noirci, et le frère aîné de sang qi a été blessé par lui!
  28. JavaScript - - quatre façons de juger les types de données
  29. HTTPS|SSL笔记-SSL分手过程(Encrypted Alert)
  30. The film arrangement rate exceeds 40%, and the box office exceeds 390 million in less than two days! Why is Changjin lake?
  31. Nouvelle grande expérience de prise de vue en direct 2022 Geely Howe
  32. Apprenez à connaître CSS - Comment organiser votre code CSS
  33. Can the Zero run C11 with less than 200000 become the leader of medium-sized pure electric SUV?
  34. Https | SSL Notes - SSL break Process (encrypted Alert)
  35. HTTPS|SSL筆記-SSL分手過程(Encrypted Alert)
  36. Récemment, j'a i été interrogé par des fans sur les génériques Java, donc j'ai regardé en arrière et j'espère que l'entrevue de mon frère cadet se passera bien.
  37. Comment utiliser la nouvelle spécification es dans votre projet
  38. JavaScript - - orienté objet
  39. South Korean actress Liu Renna, wearing a white strapless skirt and walking on the red carpet, has a hot body and attracts eyes. She smiles so sweet
  40. Nginx (3): process model
  41. Projet Java: système de gestion du rendement des employés (Java + SSM + MySQL + Maven + HTML)
  42. CSS tips | one line of code to realize the integration of avatar and national flag
  43. Maotai and Paris Fashion Week joined hands to make Chinese elements appear on the show
  44. Wang Xiaoya showed up in a sleeveless skirt and reappeared her intellectual elegance. She was still full of temperament after leaving the nest CCTV
  45. Comment écrire un document de conception frontale
  46. Créer une api javascript haute performance avec Rust et l'exécuter dans webassembly
  47. Analyse de certains principes techniques clés du SDK de surveillance frontale
  48. Point de vue: la NFT de type portrait a formé un modèle d'entreprise. Quelles sont ses perspectives d'avenir et ses difficultés?
  49. Stars celebrate the motherland's birthday in patterns: Tang Yan Bixin, Liu Xiaoqing in military uniform, Zhao Liying and he Jiong send blessings
  50. L'amour entre Wing Mei et Luan Tree: de l'amour à première vue à l'amour éternel
  51. Disappeared car companies: tape measure is useless? Zhongtai is on the verge of death and has no way to return to heaven
  52. BUUCTF [极客大挑战 2019]Http
  53. element缓存到本地使用
  54. How can the volunteer army with less steel and more gas beat the American army with more steel and less gas? Changjin Lake gives you the answer
  55. CentOS installation source package nginx error
  56. Mise en cache des éléments pour utilisation locale
  57. Disappeared car companies: tape measure is useless? Zhongtai is on the verge of death and has no way to return to heaven
  58. He saifei est si naturel!58 ans est si beau, porter des vêtements de vieillesse pour accepter de vieillir!
  59. Finally pregnant! Seven years of pregnancy, collective blessing of the entertainment industry
  60. Wu Qili sent blessings on the national day. She looked haggard and thin on her own. It was worrying