Bootstrap

【js自学打卡6】函数防抖 / 并行异步 / arr.sort /查询对象的键是否存在/获取对象的键

函数防抖 / 并行异步

1. 函数防抖debounced

力扣2627
据说面试常考

1.1 概念

“debounced"这个术语通常用于电子工程和计算机科学中,特别是在涉及开关和信号处理的场合。它的意思是对一个信号进行去抖动处理。
在物理开关中,当用户按下或释放开关时,由于机械接触的不稳定,开关的接触点可能会快速地闭合和断开多次,产生一系列的信号脉冲,这种现象称为"抖动”(bounce)。如果这些脉冲被直接用作控制信号,可能会导致错误操作或不稳定的行为。
去抖动(Debouncing)是一种技术,用于确保一个信号只在稳定状态时才被识别,从而消除由于接触抖动造成的不准确信号。在软件中,去抖动通常涉及到忽略短时间内连续出现的事件,只处理事件稳定后的第一个或最后一个事件。
例如,在网页开发中,如果用户在短时间内多次点击一个按钮,去抖动技术可以确保只响应第一次或最后一次点击,防止因为连续点击导致的多次触发同一个动作。这在处理诸如搜索框输入、窗口调整大小等事件时特别有用。

1.2 实现思路

1.闭包特性:函数内设置timer记录timeId方便clear。以及函数调用期间timer的保留
2.使用setTimeout和clearTimeout
3.return的时候先判断此时timer是否为空,不为空说明这个时候有函数准备延迟执行,然后清掉当前的timer,重新set一个。

2. 并行异步

手搓实现promise.all
力扣2721

一个疑问:为什么设置的一个计数器能保证全都运行完成然后跳出?
首先是循环中遍历的时候一定创造了promise,但只有运行到计数器增加那一行才会说明完成了promise,然后每个都判断一下完成全部没有(因为不知道谁才是最后完成的)。完成了就导出结果。

/**
 * @param {Array<Function>} functions
 * @return {Promise<any>}
 */
var promiseAll = function(functions) {
    const result = [];
    let resultCount = 0; //计数器
    return new Promise((resolve,reject)=> {
        functions.forEach((promise,index)=> {
            promise().then((value)=> { //promise()是这个异步运算的结果
            result[index] = value;
            resultCount++; //记录当前promise完成
            if(resultCount === functions.length){ //全都完成就返回
                resolve(result); //这个是最外层的resolve
            }
        },reject)
        })
    })
    
};

/**
 * const promise = promiseAll([() => new Promise(res => res(42))])
 * promise.then(console.log); // [42]
 */

3. arr.sort及fn

力扣2724
在JavaScript中,sort() 方法用于对数组的元素进行排序。当sort()方法没有传入比较函数时,默认会将元素转换为字符串,并按照字符串Unicode码点的顺序进行排序。这对于数字数组来说,可能会导致不正确的排序结果。
为了正确地对数字数组进行排序,或者按照特定的标准对数组进行排序,通常会传递一个比较函数给sort()方法。比较函数定义了数组元素的排序方式。
下面是代码return arr.sort((a, b) => fn(a) - fn(b));的解释:

  • arr.sort(): 调用数组arrsort()方法来对其进行排序。
  • (a, b) => fn(a) - fn(b): 这是一个箭头函数,作为比较函数传递给sort()方法。这个比较函数接受两个参数ab,它们代表数组中任意两个相邻的元素。
  • fn(a): 在比较函数内部,对元素a调用了一个函数fn。这个函数fn应该是之前定义好的,它会对元素a进行某种计算或转换。
  • fn(b): 同样,对元素b调用函数fn
  • fn(a) - fn(b): 比较函数的返回值是fn(a)fn(b)的差值。这个差值决定了元素ab在排序后的数组中的相对位置。
    以下是排序过程中发生的情况:
  • 如果fn(a) - fn(b)的结果小于0,那么a会被排列到b的前面。
  • 如果fn(a) - fn(b)的结果大于0,那么b会被排列到a的前面。
  • 如果fn(a) - fn(b)的结果等于0,那么ab的相对位置不变。
    这个比较函数使得数组arr按照函数fn返回的值进行排序。例如,如果数组是数字数组,并且fn是一个简单的乘以2的函数,那么数组将按照每个元素的2倍进行排序。
    这是一个示例:
function fn(x) {
  return x * 2;
}
let arr = [5, 3, 9, 1];
arr = arr.sort((a, b) => fn(a) - fn(b));
console.log(arr); // 输出可能是 [1, 3, 5, 9],因为排序是基于元素的两倍值

在这个例子中,数组arr会按照每个元素乘以2后的值进行升序排序。

4.对象的键

4.1查询是否存在某个键

在JavaScript中,你可以使用几种方法来检查一个对象是否包含特定的键(key)。

1. 使用 in 操作符

in 操作符会检查属性是否在对象中,无论是对象自身的属性还是继承自原型的属性。

const obj = { a: 1, b: 2, c: 3 };
console.log('a' in obj); // 输出: true
console.log('d' in obj); // 输出: false

2. 使用 Object.hasOwnProperty() 方法

hasOwnProperty() 方法会检查属性是否是对象自身的属性,不包括原型链上的属性。

const obj = { a: 1, b: 2, c: 3 };
console.log(obj.hasOwnProperty('a')); // 输出: true
console.log(obj.hasOwnProperty('d')); // 输出: false

3. 使用 Object.prototype.hasOwnProperty.call()

如果你不想直接在对象上调用 hasOwnProperty()(例如,如果你不确定对象是否有这个方法或者它可能被覆盖了),你可以使用 call() 方法。

const obj = { a: 1, b: 2, c: 3 };
console.log(Object.prototype.hasOwnProperty.call(obj, 'a')); // 输出: true
console.log(Object.prototype.hasOwnProperty.call(obj, 'd')); // 输出: false

4. 使用 Object.keys()Object.getOwnPropertyNames()Reflect.ownKeys()

这些方法可以返回对象自身的所有键的数组,然后你可以使用 Array.prototype.includes() 来检查数组是否包含特定的键。

const obj = { a: 1, b: 2, c: 3 };
console.log(Object.keys(obj).includes('a')); // 输出: true
console.log(Object.keys(obj).includes('d')); // 输出: false
// 或者使用 Object.getOwnPropertyNames() 或 Reflect.ownKeys()
console.log(Object.getOwnPropertyNames(obj).includes('a')); // 输出: true
console.log(Reflect.ownKeys(obj).includes('d')); // 输出: false

通常情况下,如果你只是想检查对象是否包含某个键而不关心这个键是否来自原型链,使用 in 操作符是最简单的方法。如果你需要确保检查的是对象自身的属性,应该使用 hasOwnProperty() 方法或者其安全变体。

4.2 获取对象的key

在JavaScript中,你可以使用几种不同的方法来获取对象中的键(key):

1. 使用 Object.keys() 方法

Object.keys() 方法会返回一个包含对象所有自身可枚举属性的键的数组。

const obj = { a: 1, b: 2, c: 3 };
const keys = Object.keys(obj);
console.log(keys); // 输出: ['a', 'b', 'c']

2. 使用 for...in 循环

for...in 循环可以遍历对象的所有可枚举属性(包括原型链上的属性)。

const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
  if (obj.hasOwnProperty(key)) { // 检查属性是否是对象自身的属性
    console.log(key); // 输出: 'a', 'b', 'c'
  }
}

在这里,hasOwnProperty() 方法用于确保只获取对象自身的属性,而不包括原型链上的属性。

3. 使用 Object.getOwnPropertyNames() 方法

Object.getOwnPropertyNames() 方法返回一个数组,包含对象的所有自身属性的属性名,包括不可枚举的属性。

const obj = { a: 1, b: 2, c: 3 };
const keys = Object.getOwnPropertyNames(obj);
console.log(keys); // 输出: ['a', 'b', 'c']

4. 使用 Reflect.ownKeys() 方法

Reflect.ownKeys() 方法返回一个数组,包含对象自身的所有键,包括不可枚举的属性和Symbol。

const obj = { a: 1, b: 2, c: 3 };
const keys = Reflect.ownKeys(obj);
console.log(keys); // 输出: ['a', 'b', 'c']

以上方法都可以用来获取对象中的键,但它们各有不同的使用场景。通常情况下,如果你只需要获取对象自身的可枚举属性键,Object.keys() 是最常用的方法。如果你需要包括不可枚举属性或Symbol键,则可能需要使用 Object.getOwnPropertyNames()Reflect.ownKeys()。如果你想遍历包括原型链上的属性,可以使用 for...in 循环,但要注意使用 hasOwnProperty() 过滤。

;