前端笔试之手写代码

扁平化嵌套数组/flat实现

描述:将嵌套多层的数组展开平铺成只有一层的数组。

1
2
let array = [1, [1, 2, 3], [1, [2, {}]] ]
handle(array) // [1, 1, 2, 3, 1, 2, {}]

方法一

1
2
const handle = array => JSON.parse(`[${JSON.stringify(array).replace(/\[|]/g,'')}]`)
handle(array) // [ 1, 1, 2, 3, 1, 2, {} ]

知识点JSON.parse()/JSON.stringify()String.prototype.replace()

方法二

1
2
const handle = array => array.reduce((accumulator, currentValue) => accumulator.concat(Array.isArray(currentValue) ? handle(currentValue): currentValue), [])
handle(array) // [ 1, 1, 2, 3, 1, 2, {} ]

知识点Array.prototype.reduce()Array.prototype.concat()

方法三

1
2
3
4
5
6
7
const handle = array => {
while(array.some(item => Array.isArray(item))) {
array = [].concat(...array)
}
return array
}
handle(array) // [ 1, 1, 2, 3, 1, 2, {} ]

知识点whileArray.prototype.some()剩余参数

其它方法:……

数组去重

描述:将数组中重复的元素过滤掉。

1
2
let array = [1, 2, 1, '3', '3', 0 , 1]
handle(array) // [1, 2, '3', 0]

方法一

1
2
const handle = array => [...new Set(array)]
handle(array) // [ 1, 2, '3', 0 ]

知识点:Set

方法二

1
2
3
4
5
const handle = array => array.reduce((accumulator, currentValue) => {
!accumulator.includes(currentValue) && accumulator.push(currentValue)
return accumulator
}, [])
handle(array) // [ 1, 2, '3', 0 ]

知识点:Array.prototype.includes()

方法三

1
2
3
4
5
const handle = array => {
let map = new Map()
return array.filter(item => map.has(item) ? false : map.set(item))
}
handle(array) // [ 1, 2, '3', 0 ]

知识点MapArray.prototype.filter()

其它方法:……

模拟bind实现

1
2
3
4
5
6
Function.prototype.bind = function () {
let self = this, args = Array.from(arguments), context = args.shift();
return function () {
return self.apply(context, args.concat(...arguments))
};
};

知识点apply、call、bind

模拟Call实现

1
2
3
4
5
6
7
Function.prototype.Call = function(){
let args = Array.from(arguments), context = args.shift();
context = Object(context);
context.fn = this;
let result = context.fn(...args);
return (delete context.fn) && result;
};

模拟New实现

1
2
3
4
5
6
const handle = function() {
let fn = Array.prototype.shift.call(arguments)
let obj = Object.create(fn.prototype)
let o = fn.apply(obj, arguments)
return typeof o === 'object' ? o : obj;
}

知识点Object.create()

格式化数字

1
2
3
const num = 123456789;
const handle = num => String(num).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
handle(num) // 123,456,789

知识点正则表达式String.prototype.replace()

回文判断

1
2
3
4
5
6
7
8
9
const num = 123456654321;
const str = 'abababababab';
const handle = params => {
let str_1 = String(params).replace(/[^0-9A-Za-z]/g, '').toLowerCase();
let str_2 = str_1.split('').reverse().join();
return str_1 === str_2 ? true : false
}
handle(num) // true
handle(str) // false

知识点String.prototype.split()Array.prototype.join()

函数节流

定时器

1
2
3
4
5
6
7
8
9
10
11
const handle = (fn, interval) => {
let timeId = null;
return function() {
if (!timeId) {
timeId = setTimeout(() => {
fn.apply(this, arguments)
timeId = null
}, interval)
}
}
}

知识点window.setTimeout

时间戳

1
2
3
4
5
6
7
8
9
10
const handle = (fn, interval) => {
let lastTime = 0
return function () {
let now = Date.now();
if (now - lastTime > interval) {
fn.apply(this, arguments)
lastTime = now
}
}
}

函数防抖

1
2
3
4
5
6
7
8
9
const handle = (fn, delay) => {
let timeId;
return function() {
if (timeId) clearTimeout(timeId)
timeId = setTimeout(() => {
fn.apply(this, arguments)
}, delay)
}
}

函数节流、函数防抖区别:函数节流和函数防抖较容易混淆,可以这么比喻,对于函数节流,门外有人频繁敲门,但是门卫按固定时间来决定是否开门。对于函数防抖,门外有人频繁敲门,门卫按最后一次敲门来决定是否开门。

知识点window.clearTimeout

深拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
const handle = function deepClone(params) {
if (Array.isArray(params)) {
return params.reduce((accumulator, currentValue) => {
(typeof currentValue === 'object') ? accumulator.push(deepClone(currentValue)) : accumulator.push(currentValue);
return accumulator;
}, [])
} else {
return Reflect.ownKeys(params).reduce((accumulator, currentValue) => {
(typeof params[currentValue] === 'object') ? accumulator[currentValue] = deepClone(params[currentValue]) : accumulator[currentValue] = params[currentValue];
return accumulator;
}, {})
}
}

发布订阅模式

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
class Pubsub {
constructor() {
this.handles = {}
}
subscribe(type, handle) {
if (!this.handles[type]) {
this.handles[type] = []
}
this.handles[type].push(handle)
}
unsubscribe(type, handle) {
let pos = this.handles[type].indexOf(handle)
if (!handle) {
this.handles.length = 0
} else {
~pos && this.handles[type].splice(pos, 1)
}
}
publish() {
let type = Array.prototype.shift.call(arguments)
this.handles[type].forEach(handle => {
handle.apply(this, arguments)
})
}
}

const pub = new Pubsub()
pub.subscribe('a', function() {console.log('a', ...arguments)})
pub.publish('a', 1, 2, 3)
// a 1 2 3

偏函数

1
2
3
4
const partial = 
(fn, ...presetArgs) =>
(...laterArgs) =>
fn(...presetArgs, ...laterArgs)

柯里化

1
2
3
4
5
6
7
8
9
10
11
12
13
const curry =
(fn, arity = fn.length, nextCurried) =>
(nextCurried = prevArgs =>
nextArg => {
var args = prevArgs.concat( [nextArg] );
if (args.length >= arity) {
return fn( ...args );
}
else {
return nextCurried( args );
}
}
)( [] );

函数组合

1
2
3
4
5
6
7
8
9
var compose =
(...fns) =>
result => {
var list = fns.slice();
while (list.length > 0) {
result = list.pop()( result );
}
return result;
};

简易模块依赖管理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const moduleManage = (() => {
let modules = {};
const define = (name, deps, module) => {
deps = deps.map(item => modules[item])
modules[name] = module(...deps);
};
const exports = (name) => {
return modules[name];
}
return {
define,
exports,
}
})();

Promise化

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
var promise_wrap = fn => function(){
return new Promise((resolve, reject) => {
fn(...[(error, value) => error ?
reject(error):
resolve(value), ...arguments])
})
}


// 示例:
var callback_async = (callback, x = Date.now()) => {
try {
console.log('callback_async:初始时间戳', x)
// do something now
// throw 'callback-outer: error'
setTimeout(() => {
try {
// do something in the future
// throw 'callback-inner: error'
let interval = Date.now() - x
callback && callback(null,
`callback_async:在${interval}毫秒后异步完成`)
} catch (error) {
console.log({callback})
callback(error)
}
}, 1000)
} catch (error) {
callback(error)
}
}

promise_wrap(callback_async)(1)

对象可迭代

1
2
3
4
5
6
7
8
9
10
11
12
Object.prototype.Iteration = function(){
let keys = Object.keys(this), index = 0;
return{
[Symbol.iterator](){return this},
next: () => {
let current = index++;
return current < keys.length?
{value: [keys[current], this[keys[current]]], done: false}:
{value: undefined, done: true};
}
}
}

生成器自执行器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const generator_wrap = function (generator) {
const args = [...arguments].slice(1);
const gen = generator.apply(this, args);
return new Promise((resolve, reject) => {
const handleNext = function handleNext(yield){
let next;
try {
next = gen.next(yield);
} catch (error) {
reject(error)
}
if (next.done) {
resolve(next.value)
} else {
return Promise.resolve(next.value).then(yield => {
handleNext(yield);
}, error => {
gen.throw(error);
})
}
};
handleNext();
})
};
------------- The End -------------
显示评论