001 用递归算法实现,数组长度为 5 且元素的随机数在 2-32 间不重复的值
核心是生成随机数算法,Math.random()
函数返回一个随机浮点数,浮点数范围为左闭右开区间 [0, 1)
。
function rand(arr = [], length = 5, min = 2, max = 32) {
if (arr.length < length) {
const num = Math.floor(Math.random() * (max - min + 1)) + min
if (!arr.includes(num)) {
arr.push(num)
}
return rand(arr)
}
return arr
}
002 去除字符串中的空格,根据传入不同的类型分别能去掉前、后、前后、中间的空格
算法难点:
const POSITION = Object.freeze({
left: Symbol(),
right: Symbol(),
both: Symbol(),
center: Symbol(),
all: Symbol(),
})
function trim(str, position = POSITION.both) {
switch (position) {
case POSITION.left:
str = str.replace(/^\s+/, '')
break
case POSITION.right:
str = str.replace(/\s+$/, '')
break
case POSITION.both:
str = str.replace(/^\s+|\s+$/g, '')
break
case POSITION.center:
while (str.match(/\w\s+\w/)) {
str = str.replace(/(\w)(\s+)(\w)/, '$1$3')
}
break
case POSITION.all:
str = str.replace(/\s/g, '')
break
default:
break
}
return str
}
003 去除字符串中最后一个指定的字符
function delLast(str, char) {
if (!str) return false
if (!char) return str
const index = str.lastIndexOf(char)
return str.substring(0, index) + str.substring(index + 1)
}
004 设计实现 Promise.finally
Promise.prototype.finally = function (callback) {
let P = this.constructor // 获取当前实例构造函数的引用
return this.then(
(value) => P.resolve(callback()).then(() => value), // 接受状态:返回数据
(reason) =>
P.resolve(callback()).then(() => {
throw reason
}) // 拒绝状态:抛出错误
)
}
005 设计实现 Promise.race
Promise.race(iterable)
方法返回一个 promise,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝。
Promise._race = (promises) =>
new Promise((resolve, reject) => {
promises.forEach((promise) => {
promise.then(resolve, reject)
})
})
基本和上面的例子差不多,不同点是每个传入值使用 Promise.resolve 转为 Promise 对象,兼容非 Promise 对象。
const _race = (p) => {
return new Promise((resolve, reject) => {
p.forEach((item) => {
Promise.resolve(item).then(resolve, reject)
})
})
}
006 子字符串匹配算法
从长度为 n 的字符串 S 中,查找是否存在字符串 T,T 的长度是 m,若存在返回所在位置
const find = (S, T) => {
if (S.length < T.length) return -1
for (let i = 0; i < S.length - T.length; i++) {
if (S.substr(i, T.length) === T) return i
}
return -1
}
或者使用正则:
// 方法一:
const find = (S, T) => S.search(T)
// 方法二:
const find = (S, T) => {
const matched = S.match(T)
return matched ? matched.index : -1
}
007 add(1)(2, 3) 链式调用函数
add(1); // 1
add(1)(2); // 3
add(1)(2)(3); // 6
add(1)(2, 3); // 6
add(1, 2, 3); // 6
const add = (...rest) => {
const args = [...rest]
const fn = (...re) => {
args.push(...re)
return fn
}
fn.toString = () => {
return args.reduce((a, b) => a + b)
}
return fn
}
008 如何快速从一个巨大的数组中随机获取部分元素
比如有个数组有 100K 个元素,从中不重复随机选取 10K 个元素。
/* 洗牌算法:
1.生成一个0 - arr.length 的随机数
2.交换该随机数位置元素和数组的最后一个元素,并把该随机位置的元素放入结果数组
3.生成一个0 - arr.length - 1 的随机数
4.交换该随机数位置元素和数组的倒数第二个元素,并把该随机位置的元素放入结果数组
依次类推,直至取完所需的10k个元素
*/
function shuffle(arr, size) {
let result = []
for (let i = 0; i < size; i++) {
const randomIndex = Math.floor(Math.random() * (arr.length - i))
const item = arr[randomIndex]
result.push(item)
arr[randomIndex] = arr[arr.length - 1 - i]
arr[arr.length - 1 - i] = item
}
return result
}
009 实现一个批量请求函数 multiRequest(urls, maxNum)
要求如下:
每当有一个请求返回,就留下一个空位,可以增加新的请求
所有请求完成后,结果按照 urls 里面的顺序依次打出
function multiRequest(urls, maxNum) {
const ret = []
let i = 0
let resolve
const promise = new Promise((r) => (resolve = r)) // resolve 赋值
const addTask = () => {
if (i >= urls.length) {
// 全部任务结束
return resolve()
}
const task = request(urls[i++]).finally(() => {
addTask() // 如果有任务结束,则添加新任务
})
ret.push(task)
}
while (i < maxNum) {
addTask() // 初始时添加任务至最大并发数
}
return promise.then(() => Promise.all(ret))
}
// 模拟请求
function request(url) {
return new Promise((r) => {
const time = Math.random() * 1000
setTimeout(() => r(url), time)
})
}
010 实现 Promise.retry,成功后 resolve 结果,失败后重试,尝试超过一定次数才真正的 reject
Promise.retry = function (fn, times = 3) {
return new Promise(async (resolve, reject) => {
while (times--) {
try {
const ret = await fn()
resolve(ret)
break
} catch (error) {
if (!times) reject(error)
}
}
})
}
function request() {
return new Promise((resolve, reject) => {
setTimeout(() => (Math.random() > 0.9 ? resolve(n) : reject(n)), 1000)
})
}
Promise.retry(request)
011 自增 ID
const genId = (() => {
let count = 0
return () => {
return ++count
}
})()