Классические вопросы для собеседования на большие фабрики (включая анализ) основы (1)

опрос

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

Каковы основные типы?

Существует семь основных типов

  1. null
  2. undefined
  3. boolean
  4. number
  5. string
  6. symbol(более новый стандарт)
  7. BigInt(новый стандарт)

NaNтакже принадлежатnumberтип иNaNне равный себе

Каковы характеристики базового типа?

  1. Значения примитивных типов хранятся в栈内存Простой сегмент данных
  2. Базовый тип不可变的
    • То есть его нельзя изменить принудительно:Array.prototype.sort.call('abc');(сообщит об ошибке)
  3. нет базового типа__proto__нет属性
  4. Базовый тип может быть передан基本包装类型Доступ к свойствам/методам
        // 通过包装类型访问基础类型特性
        let str = 'abc';
        console.log(str.length)
    
        // 当你调用 `str.length` 时,实际过程是这样的:
        // -> 创建String类型的一个实例
        // -> 在实例上调用指定的方法
        // -> 销毁这个实例
    
        let _str = new String(str);
        let len = _str.length;
        _str = null;
    

Как определить базовый тип?

  1. Обнаружение базовых типов может быть выполнено с помощьюtypeof,ноtypeof null === 'object'
    • nullявляется базовым типом, а не объектом
    • Из-за исторического наследия нуля (первые три цифры 000) используйтеtypeofОбнаружение нуля вызовет ошибку
        // 借鉴 Vue 源码的 object 检测方法
        function isObject (obj: any): Boolean {
            return obj !== null && typeof obj === 'object'
        }
    
  2. пройти черезObject.prototype.toString.call(Универсальный метод)
    • обнаружить[[class]]
    • Без переопределения метода toString любой объект, вызывающий собственный метод toString объекта, вернет[object type]
        // 借鉴 Vue 源码的检测方法
    
        let _toString = Object.prototype.toString;
    
        function toRawType (value: any): String {
            // 获取 从第九个到倒数第二个 字符
            // 比如 [object String]  获取 String
            return _toString.call(value).slice(8, -1)
        }
    

Как преобразуются базовые типы?

  1. При преобразовании базового типа он сначала вызоветvalueOf, а затем позвонитеtoString. (Оба метода могут быть переопределены)
  2. Среди четырех арифметических операций, кроме+Все остальные операции рассчитываются как числа, если+операция, если не все литералыобеnumber(все числа являются сложением чисел), то оно будет преобразовано в строку (toString) для сращивания

Почему 0,1 + 0,2 не равно 0,3?

следитьIEEE 754 双精度版本(64位)У стандартных языков есть проблемы. Компьютеры не распознают десятичное число, JS преобразует десятичное число в соответствующий двоичный (двоичный код:0а также1).

Итак, как использовать0а также1Представлять0.1а также0.2Шерстяная ткань?

    console.log(0.1.toString(2));
    // -> 0.0001100110011001100110011001100110011001100110011001101

    console.log(0.2.toString(2));
    // -> 0.001100110011001100110011001100110011001100110011001101

Кажется, это нормально. Почему есть ошибка?

Не забывайте: интервал точности JS примерно плюс-минус.2^53, сверх лимита будет усечено. Так что 0,1, которое вы видите, на самом деле не 0,1.

Так как же решить проблему точности JS?

  1. Текущее основное решение先乘再除
    • Например, с точностью до 2 знаков после запятой.
    • Умножьте все числа, которые нужно вычислить, на 1000.
    • После завершения расчета разделите результат на 1000.
  2. Использовать новый базовый типBigInt(плохая совместимость)

Каковы «истинные» ценности JS?

В JS есть «истинные» значения, отличные от «ложных».

Значение "false" включает 7

  1. undefined
  2. null
  3. false
  4. NaN
  5. ''
  6. 0
  7. -0

При неявном преобразовании условного суждения: «ложное» значение будет преобразовано вfalse, "истинное" значение преобразуется вtrue;

А как насчет ссылочных типов?

  1. За исключением базовых типов, все они являются ссылочными типами.
  2. Тип ссылки назначается при ее создании两个空间
    • кусок вВкл, хранить данные самого ссылочного типа (конечно объем данных будет относительно большим)
    • кусок вна, сохранить паруСсылка на данные (адрес памяти в куче хранилища, то есть указатель)
  3. Ссылочные типы изменяемы: т.е.let a={}; a.x=1;
  4. Параметр функции передается по значению, будьте осторожны, чтобы не изменить ссылку

Как определить тип ссылки?

  1. пройти черезObject.prototype.toString.callобнаружить[[class]]
  2. пройти черезinstanceofОпределить тип ссылки
  3. пройти черезconstructorОпределите тип ссылки (constructorдоступен для записи, используйте с осторожностью)

Каков принцип instanceof?

instanceofВнутренний механизм черезОпределить, можно ли найти соответствующий объект в цепочке прототипов объектаprototype

Таким образом, будет ошибка при проверке iframe, потому чтоwindow.Array.prototype !== window.frames[0].Array.prototype, поэтому нет отношения наследования

  // 实现 instanceof

  function instanceof(obj, target) {
      // 获得对象的原型
      obj = obj.__proto__
      // 判断对象的类型是否等于类型的原型
      while (true) {
        // 如果__proto__ === null 说明原型链遍历完毕
        if (obj === null) {
          return false
        }
        // 如果存在 obj.__proto__ === target.prototype
        // 说明对象是该类型的实例
        if (obj === target.prototype) {
          return true
        }
        // 原型链上查找
        obj = obj.__proto__
      }
  }

Что, если вы используете instanceof для определения базового типа?

вернусьfalseпотому что базовый тип не__proto__

    let str = '123';

    console.log(str instanceof String) // -> false

Но если вы измените статический методSymbol.hasInstanceты можешь судить

    class StringType {
        static [Symbol.hasInstance](val) {
            return typeof val === 'string'
        }
    }
    console.log(str instanceof StringType) // -> true

Давайте поговорим о массивах, не так ли?

Массив — это объект, подобный списку, данные которого также могут быть прерывистыми в памяти.

Массив должен быть линейно распределенной памятью, но метод извлечения и обновления массива JS точно такой же, как и у объекта.

  • Массив превращает индекс вколичество, который используется как атрибут.это медленнее, чем реальный массив, но удобнее в использовании.
  • Массив по сути является объектом, и его прототип наследуется отArray.prototype, вверх, а затем наследовать отObject.prototype
  • Методы массива разработаны так, чтобы быть универсальными для объектов, и объекты также могут вызывать методы массива.
        let obj = {
            '2': 3,
            '3': 4,
            'length': 2,
            'splice': Array.prototype.splice,
            'push': Array.prototype.push
        }
        obj.push(1)
        obj.push(2)
    
        console.log(obj);
        // Object(4) [empty × 2, 1, 2, splice: ƒ, push: ƒ]
    
  • использоватьdelete arr[2], не уменьшает длину, а просто удаляет соответствующий атрибут (становится пустым)

Что такое массив классов?

  1. Подобный массиву не является массивом, черезArray.isArray()вернусьfalse
  2. проход в виде массиваArray.fromможно преобразовать в массив
  3. Атрибуты должны быть индексированными (числовыми) атрибутами
  4. должно иметь свойство длины

Часто встречающиеся массивы классов

  • нить
    • Единственный родной массив классов
  • arguments
    • аргументы полностью доступны...argsвместо этого, чтобы неопределенный параметр был истинным массивом
    • аргументы удаляются в стрелочных функциях
  • DOM

[] == ![] Каков результат?

PS: спасибо за добавление @shenmo_

Преобразование типов в первую очередьvalueOfОпять такиtoString;

правильно

  1. из-за!соотношение приоритетов==высокий, выполнить первым!
  2. ![]ошибаться
  3. провестисуждение о равенстве
  4. falseпреобразовать в числа0

осталось

  1. воплощать в жизнь[].valueOf()исходное значение или []
  2. Выполните [].toString(), чтобы получить ''
  3. ''преобразовать в числа0

так:0 == 0,ответtrue

проверять:

    let arr1 = [];
    let arr2 = [];

    console.log(arr1 == !arr2) // -> true

    arr1.toString = () => {
        console.log(111)
        return 1
    }

    console.log(arr1 == !arr2) 
    // -> 111
    // -> false

Разница между == и === ?

  1. ===нет неявного преобразования
  2. ==неявное преобразование
    • {a: 1} == "[object Object]"левая будет выполнять.toString()

Как сделать условие (a == 1 && a == 2) истинным?

Все еще логика преобразования типов: базовый тип передается черезvalueOfсделать неявное преобразование

ИзменятьvalueOfметод может быть достигнут

    let a = {
        value: 0,
        valueOf: function() {
            this.value++;
            return this.value;
        }
    };
    console.log(a == 1 && a == 2);

Object.isВ чем разница между === и ?

Object.is(v1, v2)фиксированный===некоторые ошибки(-0和+0, NaN和NaN):

    // === 案例
    -0 === +0       // -> true
    NaN !== NaN     // -> false

    Object.is(-0, +0)       // -> false
    Object.is(NaN, NaN)     // -> true

Обратите внимание на WeChat «Расширенный курс по интерфейсу» и ответьте на «Vue», «React», «KOA», «Full Stack». Представлены соответствующие курсы. Статья время от времени будет присылать читающие красные конверты, так что следите за обновлениями