力扣 30 天 JavaScript 挑战 第38天 (第九题)学习了 语句表达式的区别 高级函数 promise async await 节流
开始答题
版本一:
/*** @param {Function} fn* @return {Function}*/
var once = function(fn) {let runCount=0return 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)
第二版
/*** @param {Function} fn* @return {Function}*/
var once = function(fn) {let runCount=0return 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 的基本语法
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 中抛出的异常。
- 实例对比
//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();
- 在原函数外面再包一层函数来修改或扩展函数
- 节流:限制执行频率
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
- 时间限制:如果某一个函数执行了好久还没成功,给出失败提示。
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): 有些函数计算量大,但输入相同 → 结果其实一样。下次相同输入就直接返回缓存。
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