
开始答题
版本一:
js
/**
* @param {Function} fn
* @return {Function}
*/
var once = function(fn) {
let runCount=0
return function(...args){
runCount++
runCount == 1 ? return fn(...args) :return undefined
}
};
/**
* let fn = (a,b,c) => (a + b + c)
* let onceFn = once(fn)
*
* onceFn(1,2,3); // 6
* onceFn(2,3,6); // returns undefined without calling fn
*/
报错
为ai为啥报错 ai说三木运算符? :后面只能写表达式不能写语句。return ?是语句。
语句与表达式的区别
语句是一个动作,不一定有事。表达式一定会得到一个值。
语句:
if (x > 10) { ... } // if 语句
while (true) { ... } // while 语句
return 5; // return 语句
var a = 1; // 变量声明语句
表达式:
3 + 4 // 表达式,结果是 7
x > 10 // 表达式,结果是 true 或 false
fn(1, 2) // 表达式,结果是函数返回值
a = 5 // 赋值表达式,结果是 5
即是表达式又是语句
a = 5; // 既是语句(赋值语句),又是表达式(返回 5)
第二版
js
/**
* @param {Function} fn
* @return {Function}
*/
var once = function(fn) {
let runCount=0
return function(...args){
runCount++
return runCount == 1 ? fn(...args) : undefined
}
};
/**
* let fn = (a,b,c) => (a + b + c)
* let onceFn = once(fn)
*
* onceFn(1,2,3); // 6
* onceFn(2,3,6); // returns undefined without calling fn
*/
提交通过了
看官方题解
知识点
- 高阶函数
在 JavaScript(以及很多语言)里,如果一个函数满足下面任意条件之一,就叫高阶函数:
- 函数作为参数传入(参数是函数)
- 函数作为返回值返回(返回函数)
换句话说:操作函数的函数 → 就是高阶函数
。
- 异步操作 promise 与 async await
- 它俩都是处理异步操作的,async 是promise的语法糖,通过async可以像处理同步那样处理异步。
- Promise 的基本语法
js
const p = new Promise((resolve, reject) => {
// 做一些异步的事...
// 成功时调用 resolve(值)
// 失败时调用 reject(错误)
});
new Promise(...) 创建一个 Promise 对象
里面必须传一个函数,这个函数有两个参数:resolve 和 reject
resolve(value) → 表示成功,并把结果 value 传出去
reject(error) → 表示失败,并把错误传出去
then ,catch 注是 Promise 对象的方法
then作用是:当 Promise 完成后(resolve),执行的回调函数,then里面会自动接收resolve里面传入的参数。可以使用多个then把异步操作顺序串联,上一个 then 的返回值作为下一个 then 的输入
catch作用是:处理 Promise 失败(reject)或者 then 中抛出的异常。
- 实例对比
js
//promise
const p1 = new Promise(resolve => setTimeout(() => resolve("A"), 1000));
p1.then(console.log); // 1秒后输出 "A"
//async
const p1 = new Promise(resolve => setTimeout(() => resolve("A"), 1000));
async function run() {
const result = await p1; // 等待 p1 完成,拿到值
console.log(result); // 输出 "A"
}
run();
- 在原函数外面再包一层函数来修改或扩展函数
- 节流:限制执行频率
js
function throttle(fn,delay){
let lastTime =0
return function(...args){
const now = Date.now()
if(now - lastTime > delay){
fn(args)
lastTime = now
}
}
}
// 用法:搜索时 500ms 内只发一次请求
const search = (text) => console.log("查询数据库:", text);
const throttledSearch = throttle(search, 500);
// 模拟用户频繁输入
throttledSearch("a");
throttledSearch("ab");
throttledSearch("abc");
// 最终只会间隔 >= 500ms 时才真的调用一次 search
- 时间限制:如果某一个函数执行了好久还没成功,给出失败提示。
js
function withTimeout(fn, ms) {
return function() {
return Promise.race([
fn(), // 原函数
new Promise((_, reject) => setTimeout(() => reject("超时"), ms))
]);
};
}
// 模拟一个耗时很长的异步任务
const longTask = () => new Promise(resolve => setTimeout(() => resolve("完成"), 3000));
const safeTask = withTimeout(longTask, 1000);
safeTask().then(console.log).catch(console.error);
// 1 秒后报 "超时",不会卡住
- 记忆化 (Memoization): 有些函数计算量大,但输入相同 → 结果其实一样。下次相同输入就直接返回缓存。
js
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key] !== undefined) {
return cache[key]; // 从缓存取结果
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
const slowSquare = (n) => {
console.log("计算中...");
return n * n;
};
const fastSquare = memoize(slowSquare);
console.log(fastSquare(5)); // "计算中..." 然后 25
console.log(fastSquare(5)); // 直接用缓存 → 25