【30 天 JavaScript 挑战】学习笔记

30 天 JavaScript 挑战

专为 JavaScript 初学者设计

掌握必备 JavaScript 技能

前端人,前端魂,刷完 JS 即入门!

题目地址:https://leetcode.cn/studyplan/30-days-of-javascript/

个人学习笔记:https://github.com/kaimo313/30-days-of-javascript

【001】2667. 创建 Hello World 函数

// 请你编写一个名为 createHelloWorld 的函数。它应该返回一个新的函数,该函数总是返回 "Hello World" 。/*** @return {Function}*/
var createHelloWorld = function () {return function (...args) {return "Hello World";};
};const f = createHelloWorld();
console.log(f());

【002】2620. 计数器

// 给定一个整型参数 n,请你编写并返回一个 counter 函数。
// 这个 counter 函数最初返回 n,每次调用它时会返回前一个值加 1 的值 ( n ,  n + 1 ,  n + 2 ,等等)。/*** @param {number} n* @return {Function} counter*/
var createCounter = function (n) {return function () {return n++;};
};const counter = createCounter(10);
console.log(counter());
console.log(counter());
console.log(counter());

【003】2704. 相等还是不相等

// 请你编写一个名为 expect 的函数,用于帮助开发人员测试他们的代码。
// 它应该接受任何值 val 并返回一个包含以下两个函数的对象。// toBe(val) 接受另一个值并在两个值相等( === )时返回 true 。如果它们不相等,则应抛出错误 "Not Equal" 。
// notToBe(val) 接受另一个值并在两个值不相等( !== )时返回 true 。如果它们相等,则应抛出错误 "Equal" 。// 拓展知识:抛出聚合错误(AggregateError)/*** @param {string} val* @return {Object}*/
var expect = function (val) {return {toBe: function (value) {if (val !== value) throw new Error("Not Equal");return true;},notToBe: function (value) {if (val === value) throw new Error("Equal");return true;}};
};console.log(expect(5).toBe(5));
console.log(expect(5).notToBe(5));

【004】2665. 计数器 II

// 请你写一个函数 createCounter。这个函数接收一个初始的整数值 init。并返回一个包含三个函数的对象。
// 这三个函数是:
// increment() 将当前值加 1 并返回。
// decrement() 将当前值减 1 并返回。
// reset() 将当前值设置为 init 并返回。/*** @param {integer} init* @return { increment: Function, decrement: Function, reset: Function }*/
var createCounter = function (init) {let count = init;return {increment: () => ++count,decrement: () => --count,reset: () => (count = init)};
};const counter = createCounter(5);
console.log(counter.increment());
console.log(counter.reset());
console.log(counter.decrement());

【005】2635. 转换数组中的每个元素

// 编写一个函数,这个函数接收一个整数数组 arr 和一个映射函数  fn ,通过该映射函数返回一个新的数组。
// 返回数组的创建语句应为 returnedArray[i] = fn(arr[i], i) 。
// 请你在不使用内置方法 Array.map 的前提下解决这个问题。/*** @param {number[]} arr* @param {Function} fn* @return {number[]}*/
var map = function (arr, fn) {var returnedArray = [];for (var i = 0; i < arr.length; i++) {returnedArray.push(fn(arr[i], i));}return returnedArray;
};

【006】2634. 过滤数组中的元素

// 给定一个整数数组 arr 和一个过滤函数 fn,并返回一个过滤后的数组 filteredArr 。
// fn 函数接受一个或两个参数:
// arr[i] - arr 中的数字
// i - arr[i] 的索引
// filteredArr 应该只包含使表达式 fn(arr[i], i) 的值为 真值 的 arr 中的元素。
// 真值 是指 Boolean(value) 返回参数为 true 的值。
// 请在不使用内置的 Array.filter 方法的情况下解决该问题。/*** @param {number[]} arr* @param {Function} fn* @return {number[]}*/
var filter = function (arr, fn) {var filteredArr = [];for (var i = 0; i < arr.length; i++) {if (fn(arr[i], i)) {filteredArr.push(arr[i]);}}return filteredArr;
};

【007】2626. 数组归约运算

// 给定一个整数数组 nums、一个 reducer 函数 fn 和一个初始值 init,返回通过依次对数组的每个元素执行 fn 函数得到的最终结果。
// 通过以下操作实现这个结果:val = fn(init, nums[0]),val = fn(val, nums[1]),val = fn(val, nums[2]),... 直到处理数组中的每个元素。然后返回 val 的最终值。
// 如果数组的长度为 0,则函数应返回 init。
// 请你在不使用内置数组方法的 Array.reduce 前提下解决这个问题。/*** @param {number[]} nums* @param {Function} fn* @param {number} init* @return {number}*/
var reduce = function (nums, fn, init) {var val = init;for (var i = 0; i < nums.length; i++) {val = fn(val, nums[i]);}return val;
};

【008】2629. 复合函数

// 请你编写一个函数,它接收一个函数数组 [f1, f2, f3,…, fn] ,并返回一个新的函数 fn ,它是函数数组的 复合函数 。
// [f(x), g(x), h(x)] 的 复合函数 为 fn(x) = f(g(h(x))) 。
// 一个空函数列表的 复合函数 是 恒等函数 f(x) = x 。
// 你可以假设数组中的每个函数接受一个整型参数作为输入,并返回一个整型作为输出。/*** @param {Function[]} functions* @return {Function}*/
var compose = function (functions) {// 使用 reduceRight// return function (x) {//     return functions.reduceRight((p, c) => c(p), x);// };return function (x) {if (functions.length === 0) return x;let input = x;for (const func of functions.reverse()) {input = func(input);}return input;};
};const fn = compose([(x) => x + 1, (x) => 2 * x]);
console.log(fn(4)); // 9

【009】2703. 返回传递的参数的长度

// 请你编写一个函数 argumentsLength,返回传递给该函数的参数数量。
/*** @param {...(null|boolean|number|string|Array|Object)} args* @return {number}*/
var argumentsLength = function (...args) {return args.length;
};console.log(argumentsLength(1, 2, 3)); // 3

【010】2666. 只允许一次函数调用

// 给定一个函数 fn ,它返回一个新的函数,返回的函数与原始函数完全相同,只不过它确保 fn 最多被调用一次。// 第一次调用返回的函数时,它应该返回与 fn 相同的结果。
// 第一次后的每次调用,它应该返回 undefined 。/*** @param {Function} fn* @return {Function}*/
var once = function (fn) {var called = false;return function (...args) {if (!called) {called = true;return fn.apply(this, args);}};
};let fn = (a, b, c) => a + b + c;
let onceFn = once(fn);console.log(onceFn(1, 2, 3)); // 6
console.log(onceFn(2, 3, 6)); // returns undefined without calling fn

【011】2623. 记忆函数

// 请你编写一个函数,它接收另一个函数作为输入,并返回该函数的 记忆化 后的结果。// 记忆函数 是一个对于相同的输入永远不会被调用两次的函数。相反,它将返回一个缓存值。// 你可以假设有 3 个可能的输入函数:sum 、fib 和 factorial 。//  sum 接收两个整型参数 a 和 b ,并返回 a + b 。
//  fib 接收一个整型参数 n ,如果 n <= 1 则返回 1,否则返回 fib (n - 1) + fib (n - 2)。
//  factorial 接收一个整型参数 n ,如果 n <= 1 则返回  1 ,否则返回 factorial(n - 1) * n 。
/*** @param {Function} fn* @return {Function}*/
function memoize(fn) {var cache = {};return function (...args) {var key = JSON.stringify(args);if (key in cache) {return cache[key];} else {var res = fn(...args);cache[key] = res;return res;}};
}// var memoize = (fn, cache = {}) => (...args) => cache[args.join()] ?? (cache[args.join()] = fn(...args))let callCount = 0;
const memoizedFn = memoize(function (a, b) {callCount += 1;return a + b;
});
console.log(memoizedFn(2, 3)); // 5
console.log(memoizedFn(2, 3)); // 5
console.log(callCount); // 1

【012】2723. 两个 Promise 对象相加

// 给定两个 promise 对象 promise1 和 promise2,返回一个新的 promise。promise1 和 promise2 都会被解析为一个数字。
// 返回的 Promise 应该解析为这两个数字的和。// 提示:promise1 和 promise2 都是被解析为一个数字的 promise 对象/*** @param {Promise} promise1* @param {Promise} promise2* @return {Promise}*/
var addTwoPromises = async function (promise1, promise2) {return (await promise1) + (await promise2);
};console.log(addTwoPromises(Promise.resolve(2), Promise.resolve(2)).then((res) => {console.log(res);})
); // 4

【013】2621. 睡眠函数

// 请你编写一个异步函数,它接收一个正整数参数 millis ,并休眠 millis 毫秒。要求此函数可以解析任何值。/*** @param {number} millis* @return {Promise}*/
async function sleep(millis) {return new Promise((resolve) => {setTimeout(resolve, millis);});
}let t = Date.now();
sleep(100).then(() => console.log(Date.now() - t)); // 100

【014】2715. 执行可取消的延迟函数

// 给定一个函数 fn ,一个参数数组 args 和一个以毫秒为单位的超时时间 t ,返回一个取消函数 cancelFn 。// 在 cancelTimeMs 的延迟后,返回的取消函数 cancelFn 将被调用。// setTimeout(cancelFn, cancelTimeMs)
// 最初,函数 fn 的执行应该延迟 t 毫秒。// 如果在 t 毫秒的延迟之前调用了函数 cancelFn,它应该取消 fn 的延迟执行。
// 否则,如果在指定的延迟 t 内没有调用 cancelFn,则应执行 fn,并使用提供的 args 作为参数。// fn 是一个函数
// args 是一个有效的 JSON 数组
// 1 <= args.length <= 10
// 20 <= t <= 1000
// 10 <= cancelTimeMs <= 1000/*** @param {Function} fn* @param {Array} args* @param {number} t* @return {Function}*/
var cancellable = function (fn, args, t) {var timer = setTimeout(() => {fn(...args);}, t);return function () {clearTimeout(timer);};
};const result = [];const fn = (x) => x * 5;
const args = [2],t = 20,cancelTimeMs = 50;const start = performance.now();const log = (...argsArr) => {const diff = Math.floor(performance.now() - start);result.push({ time: diff, returned: fn(...argsArr) });
};const cancel = cancellable(log, args, t);const maxT = Math.max(t, cancelTimeMs);setTimeout(cancel, cancelTimeMs);setTimeout(() => {console.log(result); // [{"time":20,"returned":10}]
}, maxT + 15);

【015】2725. 间隔取消

// 现给定一个函数 fn,一个参数数组 args 和一个时间间隔 t,返回一个取消函数 cancelFn。// 在经过 cancelTimeMs 毫秒的延迟后,将调用返回的取消函数 cancelFn。// setTimeout(cancelFn, cancelTimeMs)
// 函数 fn 应立即使用参数 args 调用,然后每隔 t 毫秒调用一次,直到在 cancelTimeMs 毫秒时调用 cancelFn。/*** @param {Function} fn* @param {Array} args* @param {number} t* @return {Function}*/
var cancellable = function (fn, args, t) {fn(...args);var timer = setInterval(() => {fn(...args);}, t);return () => clearInterval(timer);
};const result = [];const fn = (x) => x * 2;
const args = [4],t = 35,cancelTimeMs = 190;const start = performance.now();const log = (...argsArr) => {const diff = Math.floor(performance.now() - start);result.push({ time: diff, returned: fn(...argsArr) });
};const cancel = cancellable(log, args, t);setTimeout(cancel, cancelTimeMs);setTimeout(() => {console.log(result); // [//     {"time":0,"returned":8},//     {"time":35,"returned":8},//     {"time":70,"returned":8},//     {"time":105,"returned":8},//     {"time":140,"returned":8},//     {"time":175,"returned":8}// ]
}, cancelTimeMs + t + 15);

【016】2637. 有时间限制的 Promise 对象

// 请你编写一个函数,它接受一个异步函数 fn 和一个以毫秒为单位的时间 t。它应根据限时函数返回一个有 限时 效果的函数。
// 函数 fn 接受提供给 限时 函数的参数。// 限时 函数应遵循以下规则:// 如果 fn 在 t 毫秒的时间限制内完成,限时 函数应返回结果。
// 如果 fn 的执行超过时间限制,限时 函数应拒绝并返回字符串 "Time Limit Exceeded" 。// 提示:// 0 <= inputs.length <= 10
// 0 <= t <= 1000
// fn 返回一个 Promise 对象/*** @param {Function} fn* @param {number} t* @return {Function}*/
var timeLimit = function (fn, t) {return async function (...args) {return new Promise(async (resolve, reject) => {var timer = setTimeout(() => {reject("Time Limit Exceeded");}, t);try {var res = await fn(args);resolve(res);} catch (error) {reject(error);}clearTimeout(timer);});};
};// var timeLimit = function (fn, t) {
//     return async function (...args) {
//         const timeLimitPromise = new Promise((resolve, reject) => {
//             setTimeout(() => reject("Time Limit Exceeded"), t);
//         });
//         const returnedPromise = fn(...args);
//         return Promise.race([timeLimitPromise, returnedPromise]);
//     };
// };const limited = timeLimit((t) => new Promise((res) => setTimeout(res, t)), 100);
limited(150).catch(console.log); // "Time Limit Exceeded" at t=100ms

【017】2622. 有时间限制的缓存

// 编写一个类,它允许获取和设置键-值对,并且每个键都有一个 过期时间 。// 该类有三个公共方法:// set(key, value, duration) :接收参数为整型键 key 、整型值 value 和以毫秒为单位的持续时间 duration 。
// 一旦 duration 到期后,这个键就无法访问。
// 如果相同的未过期键已经存在,该方法将返回 true ,否则返回 false 。
// 如果该键已经存在,则它的值和持续时间都应该被覆盖。// get(key) :如果存在一个未过期的键,它应该返回这个键相关的值。否则返回 -1 。// count() :返回未过期键的总数。var TimeLimitedCache = function () {this.cache = new Map();
};/*** @param {number} key* @param {number} value* @param {number} duration time until expiration in ms* @return {boolean} if un-expired key already existed*/
TimeLimitedCache.prototype.set = function (key, value, duration) {let obj = this.cache.get(key);if (obj) {clearTimeout(obj.timeout);}this.cache.set(key, {value,timeout: setTimeout(() => {this.cache.delete(key);}, duration)});return Boolean(obj);
};/*** @param {number} key* @return {number} value associated with key*/
TimeLimitedCache.prototype.get = function (key) {return this.cache.has(key) ? this.cache.get(key).value : -1;
};/*** @return {number} count of non-expired keys*/
TimeLimitedCache.prototype.count = function () {return this.cache.size;
};const timeLimitedCache = new TimeLimitedCache();console.log(timeLimitedCache.set(1, 42, 1000)); // false
console.log(timeLimitedCache.get(1)); // 42
console.log(timeLimitedCache.count()); // 1

【018】2627. 函数防抖

// 请你编写一个函数,接收参数为另一个函数和一个以毫秒为单位的时间 t ,并返回该函数的 函数防抖 后的结果。// 函数防抖 方法是一个函数,它的执行被延迟了 t 毫秒,如果在这个时间窗口内再次调用它,它的执行将被取消。
// 你编写的防抖函数也应该接收传递的参数。// 例如,假设 t = 50ms ,函数分别在 30ms 、 60ms 和 100ms 时调用。
// 前两个函数调用将被取消,第三个函数调用将在 150ms 执行。
// 如果改为 t = 35ms ,则第一个调用将被取消,第二个调用将在 95ms 执行,第三个调用将在 135ms 执行。/*** @param {Function} fn* @param {number} t milliseconds* @return {Function}*/
var debounce = function (fn, t) {var timer = null;return function (...args) {if (timer) {clearTimeout(timer);}timer = setTimeout(() => {fn.apply(this, args);}, t);};
};const log = debounce(console.log, 100);
log("Hello"); // cancelled
log("Hello"); // cancelled
log("Hello"); // Logged at t=100ms

【019】2721. 并行执行异步函数

// 给定一个异步函数数组 functions,返回一个新的 promise 对象 promise。
// 数组中的每个函数都不接受参数并返回一个 promise。所有的 promise 都应该并行执行。// promise resolve 条件:// 当所有从 functions 返回的 promise 都成功的并行解析时。
// promise 的解析值应该是一个按照它们在 functions 中的顺序排列的 promise 的解析值数组。
// promise 应该在数组中的所有异步函数并行执行完成时解析。// promise reject 条件:// 当任何从 functions 返回的 promise 被拒绝时。promise 也会被拒绝,并返回第一个拒绝的原因。/*** @param {Array<Function>} functions* @return {Promise<any>}*/
var promiseAll = async function (functions) {return new Promise((resolve, reject) => {if (functions.length === 0) {resolve([]);return;}const results = new Array(functions.length).fill(null);let count = 0;functions.forEach((el, index) => {el().then((res) => {results[index] = res;count++;if (count === functions.length) {resolve(results);}}).catch((err) => {reject(err);});});});
};const promise = promiseAll([() => new Promise((res) => res(42))]);
promise.then(console.log); // [42]

【020】2727. 判断对象是否为空

// 给定一个对象或数组,判断它是否为空。// 一个空对象不包含任何键值对。
// 一个空数组不包含任何元素。
// 你可以假设对象或数组是通过 JSON.parse 解析得到的。/*** @param {Object|Array} obj* @return {boolean}*/
// 时间、空间复杂度 O(n)
var isEmpty = function (obj) {return Object.keys(obj).length === 0;
};// 时间、空间复杂度 O(1)
// var isEmpty = function (obj) {
//     for (let a in obj) return false;
//     return true;
// };

【021】2677. 分块数组

// 给定一个数组 arr 和一个块大小 size ,返回一个 分块 的数组。
// 分块 的数组包含了 arr 中的原始元素,但是每个子数组的长度都是 size 。
// 如果 arr.length 不能被 size 整除,那么最后一个子数组的长度可能小于 size 。// 你可以假设该数组是 JSON.parse 的输出结果。换句话说,它是有效的JSON。// 请你在不使用 lodash 的函数 _.chunk 的情况下解决这个问题。/*** @param {Array} arr* @param {number} size* @return {Array}*/
// var chunk = function (arr, size) {
//     const result = [];
//     for (let i = 0; i < arr.length; i += size) {
//         result.push(arr.slice(i, i + size));
//     }
//     return result;
// };// var chunk = function (arr, size) {
//     return arr.reduce((pre, next, index) => {
//         const lastChunk = pre[pre.length - 1];
//         if (!lastChunk || lastChunk.length === size) {
//             pre.push([next]);
//         } else {
//             lastChunk.push(next);
//         }
//         return pre;
//     }, []);
// };var chunk = function (arr, size) {return Array.from({ length: Math.ceil(arr.length / size) }, function (_, index) {return arr.slice(index * size, index * size + size);});
};console.log(chunk([1, 2, 3, 4, 5], 2));

【022】2619. 数组原型对象的最后一个元素

// 请你编写一段代码实现一个数组方法,使任何数组都可以调用 array.last() 方法,这个方法将返回数组最后一个元素。
// 如果数组中没有元素,则返回 -1 。/*** @return {null|boolean|number|string|Array|Object}*/
Array.prototype.last = function () {return this.length === 0 ? -1 : this[this.length - 1];
};const arr = [1, 2, 3];
arr.last(); // 3

【023】2631. 分组

// 请你编写一段可应用于所有数组的代码,使任何数组调用 array. groupBy(fn) 方法时,它返回对该数组 分组后 的结果。// 数组 分组 是一个对象,其中的每个键都是 fn(arr[i]) 的输出的一个数组,该数组中含有原数组中具有该键的所有项。// 提供的回调函数 fn 将接受数组中的项并返回一个字符串类型的键。// 每个值列表的顺序应该与元素在数组中出现的顺序相同。任何顺序的键都是可以接受的。/*** @param {Function} fn* @return {Object}*/
Array.prototype.groupBy = function (fn) {return this.reduce((acc, val) => {const key = fn(val);if (!acc[key]) {acc[key] = [];}acc[key].push(val);return acc;}, {});
};console.log([1, 2, 3].groupBy(String)); // {"1":[1],"2":[2],"3":[3]}

【024】2724. 排序方式

// 给定一个数组 arr 和一个函数 fn,返回一个排序后的数组 sortedArr。
// 你可以假设 fn 只返回数字,并且这些数字决定了 sortedArr 的排序顺序。
// sortedArr 必须按照 fn 的输出值 升序 排序。// 你可以假设对于给定的数组,fn 不会返回重复的数字。/*** @param {Array} arr* @param {Function} fn* @return {Array}*/
var sortBy = function (arr, fn) {return arr.sort(function (a, b) {return fn(a) - fn(b);});
};

【025】2722. 根据 ID 合并两个数组

// 现给定两个数组 arr1 和 arr2 ,返回一个新的数组 joinedArray 。
// 两个输入数组中的每个对象都包含一个 id 字段。
// joinedArray 是一个通过 id 将 arr1 和 arr2 连接而成的数组。
// joinedArray 的长度应为唯一值 id 的长度。返回的数组应按 id 升序 排序。// 如果一个 id 存在于一个数组中但不存在于另一个数组中,则该对象应包含在结果数组中且不进行修改。
// 如果两个对象共享一个 id ,则它们的属性应进行合并:
// 如果一个键只存在于一个对象中,则该键值对应该包含在对象中。
// 如果一个键在两个对象中都包含,则 arr2 中的值应覆盖 arr1 中的值。/*** @param {Array} arr1* @param {Array} arr2* @return {Array}*/
var join = function (arr1, arr2) {let temp = {};arr1.concat(arr2).forEach((item) => {if (!temp[item.id]) {temp[item.id] = item;} else {temp[item.id] = Object.assign(temp[item.id], item);}});return Object.values(temp).sort((a, b) => a.id - b.id);
};console.log(join([{ id: 1, b: { b: 94 }, v: [4, 3], y: 48 }], [{ id: 1, b: { c: 84 }, v: [1, 3] }]));// 另外还可以使用双指针实现

【026】2625. 扁平化嵌套数组

// 请你编写一个函数,它接收一个 多维数组 arr 和它的深度 n ,并返回该数组的 扁平化 后的结果。// 多维数组 是一种包含整数或其他 多维数组 的递归数据结构。// 数组 扁平化 是对数组的一种操作,定义是将原数组部分或全部子数组删除,并替换为该子数组中的实际元素。
// 只有当嵌套的数组深度大于 n 时,才应该执行扁平化操作。第一层数组中元素的深度被认为是 0。// 请在没有使用内置方法 Array.flat 的前提下解决这个问题。/*** @param {Array} arr* @param {number} depth* @return {Array}*/
var flat = function (arr, n) {let result = [];arr.forEach((item) => {if (Array.isArray(item) && n > 0) {result.push(...flat(item, n - 1));} else {result.push(item);}});return result;
};

【027】2705. 精简对象

// 现给定一个对象或数组 obj,返回一个 精简对象 。
// 精简对象 与原始对象相同,只是将包含 假 值的键移除。
// 该操作适用于对象及其嵌套对象。
// 数组被视为索引作为键的对象。
// 当 Boolean(value) 返回 false 时,值被视为 假 值。// 你可以假设 obj 是 JSON.parse 的输出结果。换句话说,它是有效的 JSON。/*** @param {Object|Array} obj* @return {Object|Array}*/
var compactObject = function (obj) {if (Array.isArray(obj)) {let result = [];obj.forEach((ele) => {if (Boolean(ele)) {result.push(compactObject(ele));}});return result;} else if (typeof obj === "object") {let temp = {};for (let key in obj) {if (Boolean(obj[key])) {temp[key] = compactObject(obj[key]);}}return temp;} else {return obj;}
};

【028】2694. 事件发射器

// 设计一个 EventEmitter 类。这个接口与 Node.js 或 DOM 的 Event Target 接口相似,但有一些差异。
// EventEmitter 应该允许订阅事件和触发事件。// 你的 EventEmitter 类应该有以下两个方法:// subscribe - 这个方法接收两个参数:
//     一个作为字符串的事件名和一个回调函数。当事件被触发时,这个回调函数将被调用。
//     一个事件应该能够有多个监听器。当触发带有多个回调函数的事件时,应按照订阅的顺序依次调用每个回调函数。应返回一个结果数组。
//     你可以假设传递给 subscribe 的回调函数都不是引用相同的。
//     subscribe 方法还应返回一个对象,其中包含一个 unsubscribe 方法,使用户可以取消订阅。
//     当调用 unsubscribe 方法时,回调函数应该从订阅列表中删除,并返回 undefined。
// emit - 这个方法接收两个参数:一个作为字符串的事件名和一个可选的参数数组,这些参数将传递给回调函数。
//     如果没有订阅给定事件的回调函数,则返回一个空数组。
//     否则,按照它们被订阅的顺序返回所有回调函数调用的结果数组。class EventEmitter {constructor() {this.subscribers = {};}/*** @param {string} eventName* @param {Function} callback* @return {Object}*/subscribe(eventName, callback) {if (this.subscribers[eventName]) {this.subscribers[eventName].push(callback);} else {this.subscribers[eventName] = [callback];}return {unsubscribe: () => {this.subscribers[eventName].splice(this.subscribers[eventName].indexOf(callback), 1);}};}/*** @param {string} eventName* @param {Array} args* @return {Array}*/emit(eventName, args = []) {return this.subscribers[eventName]?.map((callback) => callback(...args)) || [];}
}const emitter = new EventEmitter();// Subscribe to the onClick event with onClickCallback
function onClickCallback() {return 99;
}
const sub = emitter.subscribe("onClick", onClickCallback);console.log(emitter.emit("onClick")); // [99]
console.log(sub.unsubscribe()); // undefined
console.log(emitter.emit("onClick")); // []

【029】2695. 包装数组

// 创建一个名为 ArrayWrapper 的类,它在其构造函数中接受一个整数数组作为参数。该类应具有以下两个特性:// 当使用 + 运算符将两个该类的实例相加时,结果值为两个数组中所有元素的总和。
// 当在实例上调用 String() 函数时,它将返回一个由逗号分隔的括在方括号中的字符串。例如,[1,2,3] 。/*** @param {number[]} nums* @return {void}*/
var ArrayWrapper = function (nums) {this.nums = nums;
};/*** @return {number}*/
ArrayWrapper.prototype.valueOf = function () {return this.nums.reduce((acc, val) => acc + val, 0);
};/*** @return {string}*/
ArrayWrapper.prototype.toString = function () {// return JSON.stringify(this.nums);return `[${this.nums}]`;
};const obj1 = new ArrayWrapper([1, 2]);
const obj2 = new ArrayWrapper([3, 4]);console.log(obj1 + obj2); // 10
console.log(String(obj1)); // "[1,2]"
console.log(String(obj2)); // "[3,4]"

【030】2726. 使用方法链的计算器

// 设计一个类 Calculator 。
//      该类应提供加法、减法、乘法、除法和乘方等数学运算功能。
//      同时,它还应支持连续操作的方法链式调用。
//      Calculator 类的构造函数应接受一个数字作为 result 的初始值。// 你的 Calculator 类应包含以下方法:// add - 将给定的数字 value 与 result 相加,并返回更新后的 Calculator 对象。
// subtract - 从 result 中减去给定的数字 value ,并返回更新后的 Calculator 对象。
// multiply - 将 result 乘以给定的数字 value ,并返回更新后的 Calculator 对象。
// divide - 将 result 除以给定的数字 value ,并返回更新后的 Calculator 对象。
//      如果传入的值为 0 ,则抛出错误 "Division by zero is not allowed" 。
// power - 计算 result 的幂,指数为给定的数字 value ,并返回更新后的 Calculator 对象。(result = result ^ value )
// getResult - 返回 result 的值。// 结果与实际结果相差在 10的-5次幂 范围内的解被认为是正确的。class Calculator {/*** @param {number} value*/constructor(value) {this.result = value;}/*** @param {number} value* @return {Calculator}*/add(value) {this.result += value;return this;}/*** @param {number} value* @return {Calculator}*/subtract(value) {this.result -= value;return this;}/*** @param {number} value* @return {Calculator}*/multiply(value) {this.result *= value;return this;}/*** @param {number} value* @return {Calculator}*/divide(value) {if (value === 0) {throw new Error("Division by zero is not allowed");}this.result /= value;return this;}/*** @param {number} value* @return {Calculator}*/power(value) {this.result = Math.pow(this.result, value);// this.result **= value;return this;}/*** @return {number}*/getResult() {return this.result;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/725915.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CRM系统的操作记录,应该怎样设计?多个独立模块的操作记录不同步,如何解决?

CRM系统的操作记录&#xff0c;应该怎样设计&#xff1f; 设计CRM&#xff08;Customer Relationship Management&#xff0c;客户关系管理&#xff09;系统的操作记录功能时&#xff0c;主要目标是确保所有与客户相关的活动和交互都能够被准确、详细地追踪和记录。以下是一种…

【AAAI2023】基于神经跨度的持续命名实体识别模型

论文标题&#xff1a;A Neural Span-Based Continual Named Entity Recognition Model 论文链接&#xff1a;https://arxiv.org/abs/2302.12200 代码&#xff1a;https://github.com/Qznan/SpanKL inproceedings{zhang2023spankl,title{A Neural Span-Based Continual Named En…

ElevenLabs用AI为Sora文生视频模型配音 ,景联文科技提供高质量真人音频数据集助力生成逼真音效

随着Open AI公司推出的Sora文生视频模型惊艳亮相互联网&#xff0c;AI语音克隆创企ElevenLabs又为Sora的演示视频生成了配音&#xff0c;所有的音效均由AI创造&#xff0c;与视频内容完美融合。 ElevenLabs的语音克隆技术能够从一分钟的音频样本中创建逼真的声音。为了实现这一…

RPC——远程过程调用

一、RPC介绍 1.1 概述 RPC&#xff08;Remote Procedure Call Protocol&#xff09; 远程过程调用协议。RPC是一种通过网络从远程计算机程序上请求服务&#xff0c;不需要了解底层网络技术的协议。RPC主要作用就是不同的服务间方法调用就像本地调用一样便捷。 1.2 RPC框架 …

QT----在编译器里能够连接云端数据库,使用windeployqt打包后运行程序,链接不上云端mysql数据库

问题描述 在编译器里能够连接云端数据库&#xff0c;使用windeployqt打包后运行程序&#xff0c;链接不上云端mysql数据库&#xff0c;困扰了好几天 打包发布手机上的app还是无法连接 问题解决 打包的时候没有将这个文件放入&#xff0c;我们复制放到exe的目录即可

redis原理深入解析之看完这篇还需要努力

数据结构 动态字符串SDS struct __attribute__ ((__packed__)) sdshdr8 {uint8_t len; /*已保存的字节数 不含结束标识 header*/uint8_t alloc; /*申请总的字节数&#xff0c;不含结束标识 header*/unsigned char flags;/*不同sds头类型&#xff0c;控制sds头大小 header*/…

【AI视野·今日Robot 机器人论文速览 第八十二期】Tue, 5 Mar 2024

AI视野今日CS.Robotics 机器人学论文速览 Tue, 5 Mar 2024 Totally 63 papers &#x1f449;上期速览✈更多精彩请移步主页 Interesting: &#x1f4da;双臂机器人拧瓶盖, (from 伯克利) website: https://toruowo.github.io/bimanual-twist &#x1f4da;水下抓取器, (from …

Dynamo初学尝试梳理(五)-代码块上

“学而时习之&#xff0c;不亦说乎”&#xff0c;今天接着来&#xff0c;稍微提高点难度&#xff08;高手直接忽略就行&#xff09;。 代码块&#xff08;Code Block&#xff09;&#xff0c;是 dynamo 中可以直接输入 DesignScript 的节点。可以通过双击鼠标左键&#xff0c;快…

代码随想录算法训练营第15天| 102. 二叉树的层序遍历、226. 翻转二叉树、101. 对称二叉树

102. 二叉树的层序遍历 题目链接 102. 二叉树的层序遍历 - 力扣&#xff08;LeetCode&#xff09; 思路 这道题的正常解法&#xff08;迭代法&#xff09;二刷时能做出来&#xff0c;bugfree&#xff0c;但是递归法没有掌握。 本人题解 class Solution { public:vector<…

Rust有没有信号量机制,在缓存有数据的时候才允许等待的进程取数据?

Rust提供了信号量&#xff08;Semaphore&#xff09;机制&#xff0c;尽管它并没有直接提供类似于某些其他编程语言中的Semaphore类。然而&#xff0c;你可以使用std::sync::Mutex和std::sync::Condvar&#xff08;条件变量&#xff09;组合来实现信号量的功能。 信号量通常用…

程序员书单推荐:从入门到精通的必读之作

在程序员的职业生涯中&#xff0c;阅读技术书籍是不断学习和提升自我的重要途径。本文将为你推荐一系列从入门到精通的程序员书单&#xff0c;帮助你系统地掌握编程知识、提高技能水平&#xff0c;并在职业生涯中取得更大的进步。 一、入门篇 《Head First C语言》&#xff1…

基于SpringBoot+Vue+ElementUI+Mybatis前后端分离管理系统超详细教程(一)

Vue.js 是一个流行的前端框架&#xff0c;用于构建用户界面和单页应用程序。Vue 2 是其第二个主要版本&#xff0c;它提供了数据绑定、组件化、虚拟DOM等核心特性。要搭建一个 Vue 2 的工程化项目&#xff0c;可以遵循以下步骤&#xff1a; 一、前端环境搭建 &#xff08;一&a…

Maven入门(作用,安装配置,Idea基础maven,Maven依赖,Maven构建项目)【详解】

目录 一. Maven的作用 1.依赖管理 2.统一项目结构 3.项目构建 二.Maven安装配置 1. Maven的仓库类型 2 加载jar的顺序 3. Maven安装配置 4.安装Maven 5.配置仓库 三.idea集成maven 1.给当前project集成maven 2.给新建project集成maven 3.创建maven项目 4.pom…

二维码门楼牌管理系统应用场景:地方社区管理的新利器

文章目录 前言一、地方社区管理部门的门牌信息利用二、与社区管理部门的联动效应三、结论 前言 随着信息技术的不断发展&#xff0c;二维码门楼牌管理系统逐渐成为地方社区管理的新宠。该系统通过集成二维码技术与门楼牌信息&#xff0c;为社区管理带来了前所未有的便利与高效…

git 最基本的几条命令

git 最基本的几条命令 初始化本地仓库和推送到远程仓库 打开命令提示符或PowerShell&#xff1a;在你的本地项目目录中&#xff0c;可以通过文件资源管理器地址栏输入cmd或PowerShell 并回车来打开初始化 Git&#xff1a;git init添加所有文件到新的Git仓库&#xff1a;git a…

Github 2024-03-07Go开源项目日报 Top10

根据Github Trendings的统计,今日(2024-03-07统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目10TypeScript项目1Harbor - 开源的云原生注册表项目 创建周期:2908 天开发语言:Go协议类型:Apache License 2.0Star数量:21549 个For…

2024年JSON 面试题目-1

以下是一些可能在2024年JSON相关的热点面试题目&#xff1a; 请解释JSON是什么&#xff0c;以及它与其他数据交换格式&#xff08;如XML&#xff09;相比有哪些优势&#xff1f; JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式&#xff0c;它基于ECMAScript的一…

uniapp 解决请求出现 /sockjs-node/info?t=问题

1. uniapp请求出现 /sockjs-node/info?t问题 1.1. 问题 uniapp项目老是出现 http://192.168.2.106:8080/sockjs-node/info?t1709704280949 1.1. sockjs-node介绍 sockjs-node 是一个JavaScript库&#xff0c;提供跨浏览器JavaScript的API&#xff0c;创建了一个低延迟、全…

selinux规则

selinux状态 相关命令 进程要和文件的安全上下文相匹配&#xff0c;进程才能打开文件 查找这个命令从哪个安装包来的用 yum provides 命令 进程httpd 必须与ls -Z的文件类型一致&#xff0c;要不然在强制模式下面&#xff0c;打开不了 在终端2用此命令&#xff0c;把文件类型改…

【有趣】带照明灯的自行车“铃”

这个自行车“铃”发出的不是令行人刺耳讨厌的金属铃声&#xff0c;而是礼貌友好的“请让路&#xff0c;谢谢&#xff01;”声&#xff0c;新颖而有趣&#xff1b;照明灯则为夜间骑车带来方便&#xff0c;既保安全而又实用。整个装置成本不足10元&#xff0c;制作和安装使用也都…