Обмен технологиями

Вопросы по коду фронтального собеседования

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

В этой статье обобщены вопросы по кодированию, возникающие в процессе собеседования.

1. Переменное продвижение

2. Методы, связанные с массивами

Обратите внимание, что возвращаемое истинное значение предназначено для хранения, а не для фильтрации, поэтому не забывайте об этом. Ничего, просто я забуду, если не напишу об этом лично в течение полугода. . .

arr.filter((item, index, current) => {return arr.indexOf(item) == index});.Можно убрать вес

Суть фильтра заключается в создании нового массива, и если функция обратного вызова возвращает true, он сохраняется. Приведенная выше строка кода означает, что внутри помещается только первый раз.

Дедупликация двойного указателя:

Используйте двойные указатели, чтобы изменить порядок массива. Если они равны, быстрый указатель переместится на одну позицию вправо. Если они не равны, медленный указатель переместится на одну позицию вправо. быстрый указатель справа для сравнения со следующим разом:

  1. function doublePointer(nums) {
  2. if(nums.length < 2) {
  3. return nums;
  4. }
  5. let slow = 0;
  6. let fast = 1;
  7. let result = [nums[0]];
  8. while(fast < nums.length) {
  9. if (result[slow] == nums[fast]) {
  10. fast++;
  11. } else {
  12. slow++;
  13. result[slow] = nums[fast];
  14. fast++;
  15. }
  16. }
  17. return result;
  18. }
  19. const arr = [1,1,2,2,4,4];
  20. console.log(doublePointer(arr));

Входные [1,1,2,2,4,4] и выходные [1,2,4].

Если массив является объектом:

const arr2 = [{id:1,время: 2},{id:1,время: 4},{id:2,время: 2},{id:2,время: 4},{id:3,время: 5},

{id:3,время: 2}];

Теперь нам нужно удалить дубликаты на основе идентификатора. Если идентификаторы равны, будет сохранен только объект с наибольшим временем. Вывод:

[{"id":1,"время":4},{"id":2,"время":4},{"id":3,"время":5}]

  1. function doublePointerByorder(nums) {
  2. if(nums.length < 2) {
  3. return nums;
  4. }
  5. let slow = 0;
  6. let fast = 1;
  7. let result = [nums[0]];
  8. while(fast < nums.length) {
  9. if (result[slow].id == nums[fast].id) {
  10. if(result[slow].time < nums[fast].time) {
  11. result[slow] = nums[fast];
  12. }
  13. fast++;
  14. } else {
  15. slow++;
  16. result[slow] = nums[fast];
  17. fast++;
  18. }
  19. }
  20. return result;
  21. }

console.log(doublePointerByorder(arr2)); Вот и все.

Конечно, вы можете использовать пустой объект, чтобы запомнить его. Каждый раз сравнивайте время, соответствующее идентификатору в объекте, и выбирайте, перезаписывать ли его. После перемещения используйте цикл for in, чтобы преобразовать объект в массив. Однако двойные указатели очень эффективны, если объем данных велик, целесообразнее использовать двойные указатели.

3. Справочная информация

Присвоение знака равенства переменным ссылочного типа не влияет друг на друга.

Однако на это повлияет использование ab, которое считается поверхностной копией, как показано ниже.

  1. person1 = {name: 3};
  2. members = person1;
  3. members.name = 4;   // person1.name=4

Давайте рассмотрим классический случай, связанный с цитатами. Это также был вопрос, который я не записал, когда впервые столкнулся с ним во время интервью. Преобразуйте массив в древовидную структуру:

  1. function arrayToTree(items) {
  2. const tree = {};
  3. const map = {};
  4. items.forEach((item, index) => {
  5. const { id, parentId } = item;
  6. if (!map[id]) map[id] = { children: [] };
  7. const node = { ...item, children: map[id].children};
  8. map[id] = node;
  9. if (parentId) {
  10. if (!map[parentId]) {
  11. map[parentId] = { children: [] };
  12. } map[parentId].children.push(node);
  13. } else {
  14. tree[id] = node;
  15. }
  16. });
  17. console.log(map);
  18. }
  19. // 示例数组
  20. const items = [
  21. { id: 1, parentId: null, value: "A" },
  22. { id: 2, parentId: 1, value: "B" },
  23. { id: 3, parentId: 1, value: "C" },
  24. { id: 4, parentId: 2, value: "D" },
  25. { id: 5, parentId: 3, value: "E" }
  26. ];
  27. // 转换为树
  28. const tree = arrayToTree(items);

Вы можете скопировать его напрямую, чтобы увидеть эффект, как в случае с русской матрешкой. Легко понять, когда второй слой добавляется к первому. Трудность заключается в том, что при добавлении третьего слоя ко второму слою происходит следующее. также третий слой ниже второго слоя первого слоя. На самом деле, если вы внимательно об этом подумаете, вы можете понять, что под ["1"] есть ["1"].children["2"]. и его значение не только равно a["2"], но и все ссылки одинаковы, и выполняется a["1"].children.push(a["2"]);. Это преимущество возникает, когда выполняется a["3"]={...item, Children:[]}, выполняется a["2"].children.push(a["3"]), потому что он находится внутри данные операции, поэтому места с той же ссылкой (например, a=b, b.push также повлияет на a.push) также будут отправлены, поэтому вы увидите a["1"].children["2"] .дети а["3"]. Это правильная древовидная структура.

Если вы все еще не понимаете, вы можете попробовать следующее:

Как показано выше: b1 рассматривается как узел первого уровня a1, и изменение b1 повлияет на a1. Хотя вышеописанное представляет собой цикл, ссылки в каждой области одинаковы.

3. Макрозадачи и микрозадачи

2 4 5 синхронный код, 3 микрозадачи, 1 макрозадача.Единственная ловушка заключается в том, что 4 будет напечатано, но возврат 3 не будет выполнен.

4. Операторы сравнения

Во время неявного сравнения преобразования массив вызывает метод toString.

5. Защита от тряски и дросселирования почерка

Вам придется написать его самостоятельно. Если вы никогда этого не писали, вам придется порвать его во время собеседования, и вы, скорее всего, не сможете его вырвать.К ним относятся: немедленное выполнение с защитой от дрожания и отложенное выполнение, регулирование немедленного выполнения и отложенное выполнение.

  1. function debounce(fn, delay) {
  2. let timer = null;
  3. return function (...args) {
  4. timer && clearTimeout(timer);
  5. timer = setTimeout(() => {
  6. fn.apply(this, args);
  7. }, delay);
  8. }
  9. }
  10. function debounce_immediate(fn, delay, immediate = false) {
  11. let timer = null;
  12. let flag = true;
  13. return function (...args) {
  14. timer && clearTimeout(timer);
  15. if (immediate) {
  16. if (flag) {
  17. fn.apply(this, args);
  18. flag = false;
  19. }
  20. timer = setTimeout(() => {
  21. flag = true;
  22. }, delay);
  23. } else {
  24. timer = setTimeout(() => {
  25. fn.apply(this, args);
  26. }, delay);
  27. }
  28. }
  29. }
  30. function throttle(fn, delay) {
  31. let lastTime = 0;
  32. let timer = null;
  33. return function (...args) {
  34. const nowTime = Date.now();
  35. if (nowTime - lastTime > delay) {
  36. fn.apply(this, args);
  37. lastTime = nowTime;
  38. }
  39. }
  40. }
  41. function throttle_D(func, delayTime) {
  42. let delay = delayTime || 1000;
  43. let timer = null;
  44. return function (...args) {
  45. if (!timer) {
  46. timer = setTimeout(function () {
  47. func.apply(this, args);
  48. timer = null;
  49. }, delay);
  50. }
  51. }
  52. }

Не забудьте указать аргументы. Существенная разница между защитой от встряхивания и регулированием заключается в том, что функция предотвращения встряски всегда сбрасывает таймер, а регулирование — нет. Если регулирование всегда срабатывает, оно будет выполняться в течение определенного интервала времени и выполняться только один раз. Если защита от встряски активирована на одну минуту, она будет выполнена только один раз (немедленное выполнение или отложенное выполнение, вызванное последним щелчком мыши).