Запишите предварительное телефонное интервью с Ant Financial

опрос
Запишите предварительное телефонное интервью с Ant Financial

Координировался в Ханчжоу, закончил 18 лет, в том числе полтора года опыта разработки в стажировке. Это было интервью иностранца, с обеих сторон были интервьюеры Али.

Изначально мне прислали онлайн-оценку, но там возникла проблема с сервером, и я не мог открыть веб-страницу, поэтому мне пришлось задавать вопросы по телефону. Большинство вопросов, которые я пишу ниже, — это вопросы из оценки, а некоторые — недавно добавленные вопросы по телефону. . .

  1. Старайтесь использовать как можно больше способов добиться вертикального и горизонтального центрирования дочерних элементов.

    <div class="father">
        <div class="child">  
        </div>
    </div>
    
    <style>
        .father {
            width: 300px;
            height: 300px;
        }
        .child {
              
        }
    </style>
    

Дети делятся на множество ситуаций, грубо говоря

  • Строчные элементы: text-align + line-height
.father{
  text-align: center;
  line-height: 300px;
}
  • Фиксированная ширина и высота: абсолютная + поля
.father{
  position: relative;
}
.child{
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -150px 0 0 -150px;
}
/* 或者 */
.child{
  position: absolute;
  left: 0;
  top: 0; 
  right: 0; 
  bottom: 0;
  margin: auto;
}
  • Переменная высота: абсолютная + перевод
.father{
  position: relative;
}
.child{
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
}
  • Переменная высота: гибкий
.father{
  display: flex; 
}
.child{
  margin:auto;
}
/* 或者 */
.child{
  justify-content: center;
  align-items: center;
}
  • табличный метод:
.father{
  display: table; 
}
.child{
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}
  1. Реализуйте следующий макет с тремя столбцами всеми возможными способами, требуя, чтобы .main отображался посередине.

<div class="container">
  <div class="main"></div>
  <div class="sub"></div>
  <div class="extra"></div>
</div>
  • плавать
  • Гибкий макет: используйте свойство порядка (сортировка, на это нет ответа)
  • макет сетки: области шаблона сетки
  1. Выполните следующий код, что получится на выходе?

console.log(+false) // 0, 这里是一元运算符进行的弱类型转换,相对应的 +true 则返回 1
console.log('1' + 2 + '3' + 4) // '1234' 遇到字符串就会拼接
console.log(4 + 3 + 2 + '1')  // '91' 先加在一起再拼接
  1. Запустив приведенный ниже код, каков результат?

var x = 3;
var foo = {
  x: 2,
  baz: {
    x: 1,
    bar: function() {
      return this.x;
    }
  }
}
var go = foo.baz.bar;

console.log(go());  // 3
console.log(foo.baz.bar()); // 1

Этот вопрос основан на направлении этого:

это предоставляется вызывающей стороной и определяется тем, как вызывается функция. Если это функция, вызываемая объектом, this указывает на объект, напримерfoo.baz.bar(). Если функция вызывается независимо, например.go(), то this внутри функции указывает на undefined. Но в нестрогом режиме он будет автоматически указывать на окно глобального объекта.

  1. Реализуйте следующую функцию, чтобы вывести входную строку в обратном порядке.

function reverse(str) {
  let res = str.split('');
  return res.reverse().join('');
}

reverse('hello world!'); // output: '!dlrow olleh'

сложные вопросы

'hello world!'.reverse();  // output: '!dlrow olleh'
  • Эта проблема требует добавления методов к прототипу String, но следует учитывать некоторые модификации:
String.prototype.reverse = function reverse() {
  let res = this.split('');
  return res.reverse().join('');
}
  1. Реализовать функцию сна

Использование запроса:

/**
- 使当前运行的异步操作(promise 或者 async)停止等待若干秒
- 
- @param ms */
(async () => {
  console.log('hello')
  await sleep(2000) // 等待两秒
  console.log('world')
})()
const sleep = ms => return new Promise(resolve => setTimeout(resolve, ms))
  1. Реализовать функцию дроссельной заслонки

    Применение:

    const throFun = () => console.log('hello');
    const thro = throttle(throFun, 300);
    document.body.onscroll = () => {
      thro();  // 调用至少间隔 300 毫秒才会触发一次
    }
    
    /**
    - 频率控制,返回函数连续调用时,action 执行频率限定为 1次 / delay
    - @param delay  {number}    延迟时间,单位毫秒
    - @param action {function}  请求关联函数,实际应用需要调用的函数
    - @return {function}    返回客户调用函数 */
    function throttle(action, delay) {
      var previous = 0;
      // 使用闭包返回一个函数并且用到闭包函数外面的变量previous
      return function() {
        var _this = this;
        var args = arguments;
        var now = new Date();
        if(now - previous > delay) {
            action.apply(_this, args);
            previous = now;
        }
      }
    }
    
  2. Реализовать функцию защиты от дрожания

    Применение:

    const throFun = () => console.log('hello');
    const thro = debounce(throFun, 300);
    document.body.onscroll = () => {
      thro();  // 若一直调用则不会执行,空闲时间大于 300 毫秒才会执行
    }
    
    /**
    - 空闲控制 返回函数连续调用时,空闲时间必须大于或等于 delay,action 才会执行
    - @param delay   {number}    空闲时间,单位毫秒
    - @param action {function}  请求关联函数,实际应用需要调用的函数
    - @return {function}    返回客户调用函数 */
    function debounce(action, delay) {
      var timer; // 维护一个 timer
      return function () {
          var _this = this; // 取debounce执行作用域的this
          var args = arguments;
          if (timer) {
              clearTimeout(timer);
          }
          timer = setTimeout(function () {
              action.apply(_this, args); // 用apply指向调用debounce的对象,相当于_this.action(args);
          }, delay);
      };
    }
    
  3. Какие есть способы дедупликации массива?

const arr = [1,2,3,4,4,3,2,1];
// 方法一:new Set ES6
return [...new Set(arr)]; // 这里又问到我...的用法

// 方法二:双层for循环 (然后说这样性能不好,让我只用一层for循环的方法)
function unique(arr){
  var res=[];
  for (var i = 0; i < arr.length; i++) {
    for (var j = i+1; j < arr.length; j++) {
      if (arr[i] === arr[j]) {
        ++ i;
        j = i;
      }
    }
    res.push(arr[i]);
  }
  return res;
}

// 方法三:单层for循环 + indexOf
function unique(array){
    var res = [];
    for(var i = 0; i < array.length; i++) {
        //如果当前数组的第i项在当前数组中第一次出现的位置是i,才存入数组;否则代表是重复的
        if (array.indexOf(array[i]) === i) {
            res.push(array[i])
        }
    }
    return res;
}
// 方法三点三:或者这样
function unique(array){
    let res = [];
    for(var i = 0; i < array.length; i++) {
        if (res.indexOf(array[i]) === -1) {
            res.push(array[i]);
        }
    }
    return res;
}

// 方法四:面试官说如果可以容忍改变原有数组的情况下,怎么改进性能更好
function unique(array){
    // 注意这里一定要倒叙for循环,否则会出现问题
    for(var i = array.length - 1; i > 0; i--) { 
        if (array.indexOf(array[i]) !== i) {
            array.splice(i, 1);
        }
    }
    // 因为少声明一个变量,节省了内存空间(虽然可以忽略不计,但是面试嘛~)
    return array;
}
  1. Вопросы по сценарию, изучение делегирования событий, мониторинг событий, настраиваемые атрибуты DOM и т. д.

Описание темы:

  • На веб-странице есть элемент A с атрибутом data-href, в котором хранится адрес ссылки 🔗
  • Реализуйте функцию, когда любой щелчок, если щелкнутый элемент A или A найден в верхнем узле, ссылка перейдет

Идеи реализации:

  • Сначала добавьте в окно прослушиватель событий щелчка, а затем объявите промежуточную переменную targetNode для записи узла.
  • Затем выполните цикл, чтобы определить, имеет ли текущий узел targetNode атрибут data-href.
  • Прыгайте, если он есть, ломайтесь. Если он не существует, назначьте родительский узел узла для targetNode.
  • Цикл, пока targetNode не будет признан самым внешним узлом

Код, составленный после интервью:

window.addEventListener('click', (e) => {
    let targetNode = e.target
    while (targetNode !== document) { // 只要当前节点不是最外层document
        console.log(targetNode)
        if (targetNode.getAttribute('data-href')) { //  其实用hasAttribute更合适
            window.open(targetNode.dataset.href)
            break
        } else { // 没找到就继续往上找
            targetNode = targetNode.parentNode
        }
    }
})

Суммировать:

  • Я чувствую, что это очень хороший вопрос, и интервьюер всегда руководил моим мышлением в процессе ответа.Например, в начале я думал об использовании DOM, чтобы судить, является ли узел отношением вышестоящего-подчиненного.contains()метод, а затем интервьюер рассматривает производительность, желательно с использованием собственного API. Затем я говорю использовать parentNode. я проверил позжеMDN,ОбнаружитьcontainsЭтот метод является собственным API, который поддерживается IE5 и более поздними версиями:
    contains兼容性
    Но дело не в этом, дело в том, что этот сценарий не может быть достигнут с помощью метода contains, потому что вам нужно знать родительский узел (верхний узел). Но эта сцена ищет узел, зная дочерний узел (цель, возвращаемая событием щелчка).
  • Когда я говорил об использовании набора данных для получения пользовательских атрибутов, интервьюер сказал, что, учитывая совместимость, есть ли другой способ. Я отвечаюgetAttribute().
  • Когда я говорил о том, как находить узлы слой за слоем, я сначала подумал о рекурсивном вызове функций, но интервьюер тут же прервал меня и сказал, что это ненужно и приводит к потере производительности. Потом мне подсказали, что есть способ зациклиться. Наконец подумал о том, пока
  1. другие проблемы

  • Каковы методы массивов ES6
  • Какие инструменты управления состоянием использовались в React, а затем разница между REDUX и MOBX, и интервью встречалось три или четыре раза, поэтому оно резюмирует:

1. Redux поощряет использование приложением только одного Магазина, а Mobx поощряет использование нескольких Магазинов; 2. Redux — это функциональное программирование, а модель Mobx — объектно-ориентированная; 3. Redux использует данные «вытягивающим» способом, что согласуется с React, но Mobx использует данные «выталкивающим» способом; 4. Redux поощряет нормализацию данных и уменьшает избыточность Mobx допускает избыточность данных, но также обеспечивает согласованность данных. 5. Redux более строг, и для запуска действий по изменению состояния необходимо вызывать редюсер.Одним из первоначальных преимуществ Mobx является прямое изменение данных, но на практике все по-прежнему считают, что быть неорганизованным и недисциплинированным нехорошо. , поэтому Mobx по-прежнему предоставляет концепцию действия. В отличие от действия Redux, действие в Mobx на самом деле является функцией, и его не нужно отправлять. Если вы хотите принудительно использовать действия и запретить прямое изменение наблюдаемых данных, используйте настройку Mobx следующим образом:

import {configure} from 'mobx';

configure({enforceActions: true});
  • Давайте поговорим о виртуальном DOM реакции и кратко поговорим о принципе работы алгоритма diff.
  • Роль ключей в React