面试手册.md

// 基于发布订阅模式写一个事件事件发布订阅

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Event {
constructor() {
this.taskList = {}
}

on(eventType, fn) {
// 触发时, 明白同一个事件可能有多个任务的可能
// 所以对于task的处理我们都用数组的格式来处理
let fns = ( this.taskList[eventType] = this.taskList[eventType] || [] )
if(!fns.include(fn) {
fns.push(fn)
}
}

emiter(eventType, data) {
let fns = this.taskList[eventType]
if(Array.isArray(fns)) {
fns.map(item => {
item(data)
})
}
return this
}

off(eventType, fn) {
let fns = this.taskList[type]
if(Array.isArray(fns)) {
if(fn) {
let index = fns.indexOf(callback)
if(index !== -1) {
fns.split(index, 1)
}
}else {
fns.length = 0
}
}
return this
}
}

实现一手深拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const isType = (value) => {
return Object.prototype.toString.call(value).match(/(?<= )\w+/)[0]
// String Number Null Undefined Object Date RegExp Symbol Boolean Function Array
}
const deepClone = obj => {
let objType = isType(obj)
let result = {}
for(let i in obj) {
if(objType === 'Object' || objType === 'Array') {
result[i] = deepClone(obj[i])
}
result[i] = obj[i]
}
return result
}
a = {
a: 1,
b: {
a: 1
}
}
b = deepClone(a)

千分位

1
2
3
4
5
6
7
8
9
10
11
12
13
function exchange(num) {
num = String(num)
if(num <= 3) {
return num
}

num = num.replace(/\d{1,3}(?=(\d{3})+$)/g, (v) => {
return v + ','
})
return num
}

exchange(1230597)

模拟new关键字

1
2
3
4
5
6
7
8
9
10
function likeNew (fn, ...args) {
let o = Object.create(fn.prototype)
const result = fn.apply(o, args)
return result || o
}

function Person(name) {
this.name = name
}
likeNew(Person, 'weihaidong')

// 闭包setTimeout

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 1 setTimeout 外闭包
for(var i = 0; i < 4; i++) {
((i) => {
setTimeout(() => {
console.log(i)
}, 1000 * i)
})(i)
}
// 2 setTimeout 内闭包
for(var i = 0; i < 4; i++) {
setTimeout(((i) => {
return () => {
console.log(i)
}
})(i), 1000 * i)
}

isType函数

1
2
3
4
5
const isType = v => {
const reg = /(\.+\s+)/
return Object.prototype.toString.call(v).replace(/(\[\w+\s+)(\w+)(\])/, '$2')
}
isType(1)

古典继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Person(name) {
this.name = name
}
Person.prototype.getName = function() {
return this.name
}

function Women(name, sex) {
// 链接Person属性
Person.call(this, name)
// 初始化自身属性
this.sex = sex
}

// 链接原型链
Women.prototype = Person.prototype
// 修复constructor指向
Women.prototype.constructor = Women

快排

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const quickSort = arr => {
if(arr.length <= 1) return arr
let [min, flag, max] = arr.reduce((sum, cur, index) => {
if(index === 0) {
sum[1].push(cur)
} else {
if(cur >= sum[1]) sum[2].push(cur)
if(cur < sum[1]) sum[0].push(cur)
}
return sum
}, [[], [], []])
console.log(min, flag, max)
min = quickSort(min)
max = quickSort(max)
return [...min, ...flag, ...max]
}

quickSort([2, 1, 3, 5, 6, 1, 6, 7, 8])

二分法查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const binarySearch = (arr, x) => {
console.log(arr)
if(arr.length <= 1) {
return arr[0] === x ? x : false
}
const flag = Math.floor(arr.length / 2)
let result
if(x === arr[flag]) return result = x
if(x > flag) result = binarySearch(arr.slice(flag), x)
if(x < flag) result = binarySearch(arr.slice(0, flag), x)
return result
}
binarySearch([1, 2, 3, 4, 5, 6], 6)
binarySearch([1, 2, 3, 4, 5, 6], 7)

发布订阅

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Event {
constructor() {
this.cache = {}
}

addEvent(type, fn) {
if(this.cache[type]) {
this.cache[type].push(fn)
} else {
this.cache[type] = [fn]
}
}

emmitEvent(type, params) {
const taskList = this.cache[type]
if(taskList) {
taskList.map(item => {
item(params)
})
}
}

deleteEvent(type) {
this.cache[type] = []
}
}

const event = new Event()
event.addEvent('fly', (value) => {
console.log('i will fly', value)
})
setTimeout(() => {
event.emmitEvent('fly', 'go')
}, 2000)