手写算法: 最大子数组和

53. 最大子数组和open in new window

思路

  1. 按照加法的顺序来算,从数组的最后一位开始 ➕1,判断加完的数字是否等于 10,就是需要进位。

  2. 可以分三种情况:

  • 若无进位,那么前面也一定不会有进位的地方,直接 return 出去即可。

  • 若有进位,则当前位应该为 0,前一位 ➕1,直到加到不为 0 为止,如 499 -> 500。

  • 若有进位且一直需要进位,导致多处一位,那么就要单独处理,新建一个长度为 len+1 的新数组,全部填充 0, 首位改成 1 即可。

function plusOne(nums) {
  const len = nums.length;

  for (let i = len - 1; i >= 0; i--) {
    nums[i]++;
    // 计算加一后,是否需要进位,取模为0的话,那么就是要进位
    nums[i] %= 10;

    // 不需要进位,则直接return即可
    if (nums[i] !== 0) {
      return nums;
    }
  }
  // 判断特殊情况,全部都为9,结果超出当前数组长度,需要扩充数组
  nums = new Array(len + 1).fill(0);
  nums[0] = 1;
  return nums;
}

手写题: 手写 Selection Sort

44. 手写 Selection Sortopen in new window

用冒泡排序实现

/**
 * @param {number[]} arr
 */
function selectionSort(arr) {
  // your code here
  const len = arr.length;
  for (let i = 0; i < len - 1; i++) {
    for (let j = 0; j < len - i - 1; j++) {
      if (arr[j + 1] < arr[j]) {
        let temp = arr[j + 1];
        arr[j + 1] = arr[j];
        arr[j] = temp;
      }
    }
  }
  return arr;
}

JS 简答题

RegExp.prototype.test

40. RegExp.prototype.testopen in new window

console.log(/^4\d\d$/.test('404'));
console.log(/^4\d\d$/.test(404));
console.log(/^4\d\d$/.test(['404']));
console.log(/^4\d\d$/.test([404]));

解析

  1. 分析正则/^4\d\d$/, 表示以数字 4 开头,后跟数字,并以数字结尾

  2. RegExp.test(), 入参为string, 用来与正则表达式匹配的字符串。 如果传入的不是字符串,则先转成字符串再进行匹配。

console.log(/^4\d\d$/.test('404')); // true
console.log(/^4\d\d$/.test(404)); // true           -> 404..toString()
console.log(/^4\d\d$/.test(['404'])); // true       -> ['404'].toString()
console.log(/^4\d\d$/.test([404])); // true         -> [404].toString()

array keys

90. array keysopen in new window

console.log(Reflect.ownKeys([]));
console.log(Reflect.ownKeys([,]));
console.log(Reflect.ownKeys([1, , 2]));
console.log(Reflect.ownKeys([...[1, , 2]]));

解析

  • Reflect.ownKeys() 返回一个由目标对象自身的属性键组成的数组。
console.dir([]); // 可以看到里面只有length属性

console.dir([,]); // 同上

console.dir([1, , 2]); // 数组为:[1, empty, 3]  {0: 1, 2: 2, length: 3}, 则有三个属性

console.dir([...[1, , 2]]); // 使用扩展运算符,数组会被填充,变成 [1, undefined, 2]

setTimeout(0ms)

54. setTimeout(0ms)open in new window

setTimeout(() => {
  console.log(2);
}, 2);

setTimeout(() => {
  console.log(1);
}, 1);

setTimeout(() => {
  console.log(0);
}, 0);

解析

  1. setTimeout 每次调用定时器有个最小间隔是 4ms

  2. 2ms足以让其他任务被推送到它之前的队列中,然而1ms是不够的,按照顺序执行被推送,所以先推 1,再到 0,最后才是 2

  3. 不同浏览器不同表现机制,因为底层实现可能不同。这里只针对 google 浏览器分析。

结果为:1 -> 0 -> 2


Proxy II

82. Proxy IIopen in new window

class Dev {
  #name;
  constructor(name) {
    this.#name = name;
  }
  get name() {
    return this.#name;
  }
}

const dev = new Dev('BFE');
console.log(dev.name);

const proxyDev = new Proxy(dev, {});
console.log(proxyDev.name);

解析

class Dev {
  #name; // 私有变量
  constructor(name) {
    this.#name = name;
  }
  get name() {
    return this.#name;
  }
}

const dev = new Dev('BFE');
console.log(dev.name); // 通过调用get name 拿到

const proxyDev = new Proxy(dev, {}); // 代理dev这个对象
console.log(proxyDev.name); // 此时读的是代理完后的对象,不允许读取私有变量,报错

思考 🤔:怎么样才可以拿到呢?

可以通过反射拿到

const proxyDev = new Proxy(dev, {
  get(target, key) {
    return Reflect.get(target, key);
  },
});
console.log(proxyDev.name);
const obj = {
  dev: 'bfe',
  a: function() {
    return this.dev;
  },
  b() {
    return this.dev;
  },
  c: () => {
    return this.dev;
  },
  d: function() {
    return (() => {
      return this.dev;
    })();
  },
  e: function() {
    return this.b();
  },
  f: function() {
    return this.b;
  },
  g: function() {
    return this.c();
  },
  h: function() {
    return this.c;
  },
  i: function() {
    return () => {
      return this.dev;
    };
  },
};

console.log(obj.a());
console.log(obj.b());
console.log(obj.c());
console.log(obj.d());
console.log(obj.e());
console.log(obj.f()());
console.log(obj.g());
console.log(obj.h()());
console.log(obj.i()());
Last Updated:
Contributors: kk