近期遇到两个有意思的面试题目,所以给大家分享这两个前端题。
问题1
在node环境实现一个相加的函数add,add函数有两个参数(a,b),返回的结果是a+b,要求该函数实现a+b时如果已经计算过一次a+b,那么从上一次的计算结果拿。
解析:
由于是node环境不能使用window全局对象,优先考虑使用闭包函数来实现,闭包可以让变量运行不销毁。
什么是闭包
在JavaScript中,闭包(Closure)是一个非常重要的概念,它涉及到函数和词法作用域。闭包可以定义为:
当一个函数可以记住并访问在其外部定义的变量时,即使在其外部函数已经返回后,这个函数就形成了一个闭包。
换句话说,闭包是由函数和与其相关联的词法环境组合而成的实体。当一个函数在另一个函数内部定义时,它可以访问外部函数的变量和参数,即使外部函数已经执行完毕并且从调用栈中弹出,这些变量仍然对内部函数可见。这种现象是因为内部函数在创建时捕获了外部函数的词法环境,使得它可以在以后的任何时候访问这些变量,即便是在外部函数已经返回之后。
闭包的形成主要依赖于以下几点:
闭包的使用场景包括但不限于:
然而,闭包也可能会导致一些问题,例如:
理解闭包对于有效地编写和优化JavaScript代码至关重要。
使用闭包来实现add函数的代码如下:
function createAddFunction() {
const cache = {}; // 创建一个对象用于缓存结果
function add(a, b) {
// 生成一个唯一的键,用于在缓存中查找或存储结果
const key = `${a},${b}`;
// 检查缓存中是否已经有这个计算结果
if (cache[key] !== undefined) {
return cache[key]; // 如果存在,则直接返回缓存的结果
} else {
console.log('读取缓存计算:', a, b)
}
// 如果缓存中没有结果,进行计算并将结果存储到缓存中
const result = a + b;
cache[key] = result;
return result;
}
return add; // 返回add函数,它现在具有缓存功能
}
// 使用createAddFunction创建具有缓存能力的add函数
const add = createAddFunction();
// 测试add函数
console.log(add(1, 2)); // 第一次计算1+2,结果会被缓存
console.log(add(1, 2)); // 第二次调用,直接从缓存获取结果
console.log(add(3, 4)); // 计算3+4,结果会被缓存
console.log(add(3, 4)); // 直接从缓存获取3+4的结果
执行结果
问题2
众所周知js中的promise.all 会并发执行多个promise,只要其中一个promise失败就catch该promise失败的结果。
现在需要实现一个allRun的方法,接受多个promise,按顺序返回所有的执行结果。
解析:使用 reduce
函数来构建一个 Promise 链,每个 Promise 在链中按顺序执行。我们维护一个 results
数组和一个 index
变量,用于记录每个 Promise 的执行结果。每个 Promise 要么 resolve 并将结果添加到 results
数组中,要么 reject 并将错误添加到数组中。最后,当我们完成所有 Promise 的处理后,返回一个包含所有结果的 results
数组
function allRun(promises) {
const results = [];
let index = 0;
return promises.reduce((chain, promise) => {
return chain.then(() => {
return promise
.then(value => {
results[index++] = { status: 'fulfilled', value };
})
.catch(reason => {
results[index++] = { status: 'rejected', reason };
});
});
}, Promise.resolve())
.then(() => results);
}
// 使用示例
const promise1 = Promise.resolve('Success 1');
const promise2 = Promise.reject(new Error('Error 2'));
const promise3 = Promise.resolve('Success 3');
allRun([promise1, promise2, promise3])
.then(results => {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`Promise ${index + 1} resolved with:`, result.value);
} else {
console.log(`Promise ${index + 1} was rejected with:`, result.reason);
}
});
})
.catch(console.error);
执行结果: