Q1:防抖函数
function debounce(fn, wait, immedidate) {
// TODO
let timer = nulll;
return function(...args) {
const context = this
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(context, args)
}, wait)
}
}
Q2:节流
function throttle(cb, delay) {
let timer = null
return function(...args) {
if(timer) return
timer = setTimeout(() => {
cb.apply(this, args)
timer = null
}, delay)
}
}
Q3:给定一个只包括{、}、(、)、[、]的字符串,判断其是否有效
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合
- 左括号必须以正确的顺序闭合
示例1: s = '{}' // true
示例2: s = '{[]}' // true
示例3: s = '{' // false
示例4: s = '{[}]' // false
function isValid(str) {
// TODO
let res = true
const mapStr = {
"[":"]",
"{":"}",
"(":")",
}
for (var i = 0 ; i < str.length / 2 ; i++) {
if(mapStr[str[i]] !== str[str.length-1-i]) return false
}
return res
}
Q4:找出字符串中最长连续子串
示例:
- "aaabbcc" // aaa
- "abc" // a
function fn(str) {
let currentIdx = 1
let maxIdx = 1
let currentStr = str[0]
let maxStr = str[0]
for (let i = 1 ; i < str.length ; i++) {
if(str[i] === str[i-1]) {
currentStr += str[i]
currentIdx++
} else {
currentStr = str[i]
currentIdx = 1
}
if(currentIdx > maxIdx){
maxIdx = currentIdx
maxStr = currentStr
}
}
return maxStr
}
Q5:请手写实现一个简易的Ajax
function myAjax() {
// 创建一个 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();
// 设置请求的类型和 URL
xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);
// 设置请求头(可选)
xhr.setRequestHeader('Content-Type', 'application/json');
// 注册事件监听器,当请求状态变化时触发
xhr.onreadystatechange = function () {
// 检查请求是否完成
if (xhr.readyState === 4) {
// 检查请求是否成功
if (xhr.status === 200) {
// 解析响应文本
const response = JSON.parse(xhr.responseText);
// TODO
} else {
}
}
};
// 发送请求
xhr.send();
}
Q6:使用setTimeout实现setInterval
const mySetInterval = (cb, delay) => {
cb()
const intervalId = setTimeout(() => {
// 清除前一个 setTimeout,防止在回调函数执行时间较长时产生累积的延迟
clearTimeout(intervalId);
// 递归调用 mySetInterval
mySetInterval(cb, delay);
}, 1000)
}
mySetInterval(() => console.log("Hello, setInterval"), 1000)
Q7:给定一个整数数组arr,其中有些元素出现两次而其他元素出现一次。找到所有出现两次的元素。你可以不用到任何额外空间并在o(n)时间复杂度内解决这个问题吗?
function fn(arr) {
return arr.filter((num, index) => arr.indexOf(num) !== index);
}
同事说indexOf也是一次遍历,这里的时间复杂度是平方n
chatgpt给的答案如下:
function fn(arr) {
const seen = new Set();
const duplicates = new Set();
for (const num of arr) {
if (seen.has(num)) {
duplicates.add(num);
} else {
seen.add(num);
}
}
return Array.from(duplicates);
}
Q8:单位转换:后端返回一个数字,单位是kb,前端要展示成 KB,MB 等形式。
function formatSizeUnits(kb) {
const sizeArr = ['KB', 'MB', 'GB', 'TB', 'PB'];
let sizeIndex = 0;
while(kb >= 1024 && sizeIndex < sizeArr.length) {
kb = kb/1024;
sizeIndex++;
}
return `${kb.toFixed(2)}${sizeArr[sizeIndex]}`
}
console.log(formatSizeUnits(55));
console.log(formatSizeUnits(1024));
console.log(formatSizeUnits(5201314));
console.log(formatSizeUnits(1073741824));
Q9: Array.prototype.flat()
function _flat(n = 1) {
let res = [];
if (!n) return this;
for (let i = 0; i < this.length; i++) {
if (Array.isArray(this[i])) {
res = res.concat(_flat.call(this[i], n - 1)); // 使用 call 来调用 _flat
} else {
res.push(this[i]);
}
}
return res;
}
Array.prototype.flat = _flat;
let arr = [1, 2, [3, 4, [5, 6, [7, 8]]], 9, 10];
console.log(arr.flat()); // 输出: [1, 2, 3, 4, [5, 6, [7, 8]], 9, 10]
console.log(arr.flat(2)); // 输出: [1, 2, 3, 4, 5, 6, [7, 8], 9, 10]
console.log(arr.flat(Infinity)); // 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Q10:URL参数解析
function parseParam(url) {
const paramsStr = /.+\?(.+)$/.exec(url)[1]; // 将 ? 后面的字符串取出来
const paramsArr = paramsStr.split('&'); // 将字符串以 & 分割后存到数组中
let paramsObj = {};
// 将 params 存到对象中
paramsArr.forEach(param => {
if (/=/.test(param)) { // 处理有 value 的参数
let [key, val] = param.split('='); // 分割 key 和 value
val = decodeURIComponent(val); // 解码
val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字
if (paramsObj.hasOwnProperty(key)) { // 如果对象有 key,则添加一个值
paramsObj[key] = [].concat(paramsObj[key], val);
} else { // 如果对象没有这个 key,创建 key 并设置值
paramsObj[key] = val;
}
} else { // 处理没有 value 的参数
paramsObj[param] = true;
}
})
return paramsObj;
}
Q11:startWith 与 indexOf 相互实现
indexOf 实现 startWith
const str = 'abc';
function _startWith(s) {
return this.indexOf(s) === 0;
}
String.prototype.startsWith = _startWith;
console.log(str.startsWith('a'));
console.log(str.startsWith('ab'));
console.log(str.startsWith('b'));
startWith 实现 indexOf
const str = 'abc';
function _indexOf(s) {
if (!s) return -1;
let index = 0;
let _str = this.toString();
while (!_str.startsWith(s)) {
index++;
_str = _str.slice(1);
if (!_str.length) {
return -1;
}
}
return index;
}
String.prototype.indexOf = _indexOf;
console.log(str.indexOf('bc'));
console.log(str.indexOf('ef'));
Q12:实现一个支持链式调用的类
class Haha {
value = 0;
add (num) {
this.value += num;
return this;
}
sub (num) {
this.value -= num;
return this;
}
getValue () {
return this.value;
}
}
console.log(new Haha().add(3).add(4).add(5).getValue()) // 12
console.log(new Haha().add(3).add(4).sub(5).getValue()) // 2
Q13:实现一个sum函数
支持
sum(2,3) // 5
sum(2)(3) // 5
const sum = (x, y) => {
if(!y) {
return function(y) {
return x+y;
}
}
return x+y;
}
效果
Q14:统计数字
计算数字k在0到n中的出现的次数,k可能是0~9的一个值
例如n=12,k=1,在 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],我们发现1出现了5次 (1, 10, 11, 12)
const digitCounts = (n, k) => {
let num = 0;
for (let i = 0 ; i <= n ; i++) {
if (String(i).indexOf(k) !== -1) {
num += String(i).split(k).length - 1;
}
}
return num;
}
console.log(digitCounts(12, 1)) // 5