Душевная пытка нативного JavaScript, сколько можно ответить (1)

внешний интерфейс JavaScript
Душевная пытка нативного JavaScript, сколько можно ответить (1)

Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность

Эта статья участвовала в "Проект «Звезда раскопок»”, чтобы выиграть творческий подарочный пакет и бросить вызов творческим поощрительным деньгам.

предисловие

Портал:Душевная пытка нативного JavaScript, сколько можно ответить (2)

В текущей фронтенд-разработке три основных фреймворка занимают три трети мира Простота и мощь фреймворка не позволяют нам остановиться, используя нативныйJavaScriptВсе меньше и меньше.

но я думаюJavaScriptВ качестве основы каждого фронтенд-инженера необходимо не только учиться, но и хорошо учиться и хорошо учиться, и не будет преувеличением учиться этому много раз.

С другой стороны, во фронтовых интервью все больше внимания уделяется нативнымJavaScriptДоля расследований также увеличивается.

Я взял вопросы онлайн-интервью этого года и лично на Nioke, о500Левые и правые вопросы, роднойJavaScriptСложность (замыканий,eventLoop,this, вручную рви нативный JS) частота проверок очень высока.

Я все еще работаю над полным анализом, и я надеюсь, что вы поддержите меня, когда придет время.

Поэтому я решил отсортироватьJavaScriptВ точках знаний, которые легко проигнорировать или запутать, напишите серию статей, в пути пытки души, систематически и полностью возьмите всех, чтобы изучить оригиналJavaScriptМир, я надеюсь принести вам урожай.

Вопрос типа JS — концепция и обнаружение

1. Какие типы данных есть в JS?

  1. Базовые типы данных: всего 7 типов
Boolean Number String undefined null Bigint Symbol

Symbol:ES6Вводится новое примитивное значение, представляющее уникальное значение, в основном для решения проблемы конфликта имен атрибутов.

Bigint:ES2020новое дополнение, болееNumberТипы имеют более широкий диапазон целых чисел.

  1. Тип справочных данных: 1
Object对象(包括普通Object、Function、Array、Date、RegExp、Math)

2. Вы действительно понимаете typeof?

  1. typeofроль?

    Различая типы данных, можно вернуть 7 типов данных:number、string、boolean、undefined、object、function,так же какES6добавленsymbol

  2. typeofМожно ли правильно различать типы данных?

    не можем. Для примитивных типов, кромеnullмогут быть правильно оценены; для эталонных типов, кромеfunction, вернусь"object"

  3. typeofМеры предосторожности

    • typeofВозвращаемое значениеstringФормат, обратите внимание на такие вопросы:typeof(typeof(undefined)) -> "string"
    • typeofНеопределенные переменные не сообщают об ошибке и возвращают"undefiend"
    • typeof(null) -> "object": давнийbug
    • typeofНевозможно отличить массив от обычного объекта:typeof([]) -> "object"
    • typeof(NaN) -> "number"
  4. упражнение

console.log(typeof(b));
console.log(typeof(undefined)); 
console.log(typeof(NaN)); 
console.log(typeof(null)); 
var a = '123abc'; 
console.log(typeof(+a)); 
console.log(typeof(!!a)); 
console.log(typeof(a + "")); 
console.log(typeof(typeof(null)));
console.log(typeof(typeof({})));

Отвечать

undefined // b未定义,返回undefined
undefined
number // NaN 为number类型
object
number // +a 类型转换为NaN
boolean
string
string // typeof(null) -> "object"; typeof("object") -> "string"
string

3. Что такое instanceof? Можете ли вы смоделировать реализацию instanceof?

  1. instanceofОпределяет, существует ли прототип конструктора в цепочке прототипов объекта. Могут быть определены только ссылочные типы.
  2. instanceofчасто используется, чтобы судитьAЭтоBслучай
// A是B的实例,返回true,否则返回false
// 判断A的原型链上是否有B的原型
A instaceof B
  1. Реализация моделированияinstanceof

Идея: найти цепочку прототипов

function instance_of(Case, Constructor) {
    // 基本数据类型返回false
    // 兼容一下函数对象
    if ((typeof(Case) != 'object' && typeof(Case) != 'function') || Case == 'null') return false;
    let CaseProto = Object.getPrototypeOf(Case);
    while (true) {
        // 查到原型链顶端,仍未查到,返回false
        if (CaseProto == null) return false;
        // 找到相同的原型
        if (CaseProto === Constructor.prototype) return true;
        CaseProto = Object.getPrototypeOf(CaseProto);
    }
}

тестовое задание:

console.log(instance_of(Array, Object)) // true
function User(name){
    this.name = name;
}
const user = new User('zc');
const vipUser = Object.create(user);
console.log(instance_of(vipUser, User)) // true

4. Как отличить массив от объекта? Надежно ли использовать instanceof для оценки массива?

  1. ES6предоставлен новый методArray.isArray()
  2. если не существуетArray.isArray()Шерстяная ткань? можно использоватьObject.prototype.toString.call()Судя по всему, этот метод имеет наилучшую совместимость.
if (!Array.isArray) {
    Array.isArray = function(o) {
        return typeof(o) === 'object' 
               && Object.prototype.toString.call(o) === '[object Array]';
    }
}
  1. instanceofсудить

Метод суждения

// 如果为true,则arr为数组
arr instanceof Array

instanceofОпределить тип массива так просто, почему это не рекомендуется?

instanceofПроблема с операторами заключается в том, что если их несколькоiframe, то их будет несколькоArrayКонструктор, в данный момент будет проблематично определить, является ли это массивом.

Для получения более подробной информации, пожалуйста, обратитесь к сообщению в блоге:Почему JavaScript не использует instanceof для обнаружения массивов?

5. Как определить, является ли число NaN?

NaNимеет особую особенность,NaNне равно никакому значению, в том числе самому себе

NaN === NaN // false
NaN == NaN // false

Ввиду этой уникальной особенности относительно простая функция суждения может быть разорвана вручную.

function isNaN(x) {
    return x != x;
}
  • глобальная функцияisNaNМетод: не рекомендуется.MDNВведение к нему такое:isNaNФункции содержат несколько очень интересных правил.

Но дабы избежать некоторых непопулярных вопросов от некоторых интервьюеров, давайте немного разберемсяisNaNИнтересный механизм: сначала он будет судить, является ли параметрNumberтипа, если нетNumbertype попытается преобразовать этот параметр вNumberвведите, а затем оцените, является ли этоNaN.

Например:

// 为什么对象会带来三种不同的结果
// 是不是很有趣
// 具体原因可以参考类型转换篇
console.log(isNaN([])) // false
console.log(isNaN([1])) // false
console.log(isNaN([1, 2])) // true 
console.log(isNaN(null)) // false
console.log(isNaN(undefined)) // true

isNaNРезультат во многом зависит отNumber()результат преобразования типа, оNumberРезультаты преобразования , будут представлены в специальной части позже.

  • Number.isNaN(Рекомендуемое использование)

а такжеisNaN()в сравнении с,Number.isNaN()Не самопреобразует аргумент в число, только значение параметра NaNномер, он вернетсяtrue.

6. Как реализовать полнофункциональную функцию определения типа?

Object.prototype.toString.call([value]), можно точно определить тип данных, поэтому можно инкапсулировать свои по этому принципуtypeметод.

toString.call(()=>{})       // [object Function]
toString.call({})           // [object Object]
toString.call([])           // [object Array]
toString.call('')           // [object String]
toString.call(22)           // [object Number]
toString.call(undefined)    // [object undefined]
toString.call(null)         // [object null]
toString.call(new Date)     // [object Date]
toString.call(Math)         // [object Math]
toString.call(window)       // [object Window]

Вопросы о типах JS — преобразование типов

7. В чем разница между методами toString и valueOf?

  1. Основы: Эти два метода относятся кObjectобъект, решитьJavaScriptПроблема работы и отображения значений. Чтобы лучше выполнять свои функции, многиеJavaScriptВстроенные объекты переопределяют оба метода.
  2. toString(): возвращает строковую форму текущего объекта;valueOf(): возвращает исходное значение объекта
  3. Сравнение возвращаемых значений двух методов по каждому типу
Типы valueOf toString
Array[1,2,3] Сам массив [1, 2, 3] 1,2,3
Object сам объект [object Object]
Логический тип Логическое значение "правда или ложь"
Function сама функция function fnName(){code}
Number Численная величина Числовое представление символов
Date Временная метка в мм формате Строка времени в формате GMT
  1. приоритет вызова

    Вызывается автоматически при неявном преобразованииtoStringа такжеvalueOfметод, приоритет двух следующий:

    • При приведении к строковому типу он вызывается первымtoStringметод
    • При приведении к числовому типу он вызывается первымvalueOfметод
    • При использовании оператора оператор,valueOfприоритет надtoStirng
    • Преобразование типа объекта см. Следующий вопрос.

8. Знаете ли вы, что такое процесс преобразования объекта в примитивное значение (ToPrimitive)?

Преобразование объекта в примитивный тип вызовет встроенный[ToPrimitive]функция

(Справочный блог:Глубокое понимание преобразований типов JavaScript из спецификации ECMA.)

  • ToPrimitiveМетод принимает два параметра, один из которых является входным значением.input, один тип, который, как ожидается, будет преобразованPreferredType
    1. Если не прошел вPreferredTypeпараметр, пустьhintравный'default', что будет позжеhintпревратиться в'number'
    2. еслиPreferredTypeдаhint String,Позволятьhintравный'string'
    3. еслиPreferredTypeдаhint Number,Позволятьhintравный'number'
    4. вернутьOrdinaryToPrimitive(input, hint)
  • OrdinaryToPrimitive(input, hint)
    1. еслиhintда'string', тоmethodNamesУстановить какtoString、valueOf
    2. еслиhintда'number', тоmethodNamesУстановить какvalueOf、toString

methodNameХранилище в настоящее времяpreferredTypeЕсли приоритет вызова не преобразуется в исходное значение после завершения всех вызовов, произойдет ошибка.

9. Можете ли вы ответить на следующий вопрос?

const a = {x:1};
const b = {x:2};
const obj = {};
obj[a] = 100;
obj[b] = 200;

console.log(obj[a]);
console.log(obj[b]);

При знании седьмого и восьмого вопросов эта задача не представляет сложности.JavaScriptКлючи объектов должны быть строками, поэтому объект должен бытьaа такжеbПеревести вstringТипы. Конкретный процесс преобразования:

// 1.执行ToPrimitive
// hint 为 string
ToPrimitive(a, 'hint String')
// 2.执行OrdinaryToPrimitive
OrdinaryToPrimitive(a, 'string')
// 3.返回methodNames
methodNames = ['toString', 'valueOf']
// 4.调用methodNames里方法
// 调用toString
a.toString() // 返回[object Object]

объектaа такжеbПреобразованный результат[object Object],objК объекту добавляется только одно свойство[object Object].

Отвечать

200
200

10. Можете ли вы разобраться с преобразованием типов?

Сначала вам нужно знать:JavaScript, Толькотри типапреобразование

  • Перевести вNumberТипы:Number() / parseFloat() / parseInt()
  • превратиться вStringТипы: String() / toString()
  • превратиться вBooleanТипы:Boolean()

Итак, столкнулись с проблемами преобразования типов, просто нужно разобраться вкакая сценаПеревести вэтот типВот и все.

преобразовать в логическое значение

  • Явно:Booleanметоды могут явно преобразовывать значения в логический тип
  • Неявный: обычно срабатывает, когда есть логическое суждение или логический оператор (|| && !)
Boolean(1)   // 显式类型转换
if (1) {}    // 逻辑判断类型触发隐式转换
!!1          // 逻辑运算符触发隐式转换
1 || 'hello' // 逻辑运算符触发隐式转换

booleanтолько типtrueа такжеfalseДва вида стоимости.

разделить на значение0, -0, null, NaN, неопределенная или пустая строка ("")дляfalse, все остальноеtrue

преобразовать в строку

  • Явно:Stringметоды для явного преобразования значений в строки
  • Скрытый:+Оператор имеет один побочный операндstringвведите время

превратиться вstringХарактер типа:Часть, которую нужно преобразовать в строку, вызывает собственный метод toString (null/undefined возвращает null и undefined в строковом формате).

Когда преобразованное значение является объектом, это эквивалентно выполнениюToPrimitive(input, 'hint String')

String([1,2,3]) // 1,2,3
String({x:1}) // [object Object]

1 + '1' // 11
1 + {} // 1[object Object]

преобразовать в число

  • Явно:Numberметоды могут явно преобразовывать значения в числовые типы

Numberконкретные правила,ES5Спецификация даетСоответствующая таблица результатов

Типы результат
undefined NaN
null +0
Boolean NaN
undefined Параметр имеет значение true и возвращает 1; false возвращает +0.
Number вернуть значение, равное
String Несколько сложно, пример
Object Сначала выполните метод ToPrimitive, а затем выполните преобразование типа Number.
  1. String: вернуть пустую строку0, появится любой недопустимый числовой символ, возвратNaN
console.log(Number("1 3")) // NaN
console.log(Number("abc")) // NaN
console.log(Number("1a")) // NaN
console.log(Number("0x11")) // 17
console.log(Number("123")) // 123
console.log(Number("-123")) // -123
console.log(Number("1.2")) // 1.2
  • Скрытый:numberНеявное преобразование типов более сложное, и часть, требующая неявного преобразования, выполняетсяNumber:
    • сравнить операции (<, >, <=, >=)
    • побитовые операции (| & ^ ~)
    • арифметические операции (+ - * / %) Уведомление:Когда операнд + существует в строке, он преобразуется в строку
    • Один юань+-действовать

11. Неявные правила преобразования для ==

  1. ==: требуется только равенство значений, равенство типов не требуется;null, undefinedсуществует==равны друг другу и равны между собой
  2. ==Правила преобразования для:
Сравниваемое число B
Number String Boolean Object
Сравнительный номер
Number A == B A == ToNumber(B) A == ToNumber(B) A == ToPrimitive(B)
String ToNumber(A) == B A == B ToNumber(A) == ToNumber(B) ToPrimitive(B) == A
Boolean ToNumber(A) == B ToNumber(A) == ToNumber(B) ToNumber(A) == ToNumber(B) ToNumber(A) == ToPrimitive(B)
Object ToPrimitive(A) == B ToPrimitive(A) == B ToPrimitive(A) == ToPrimitive(B) A === B

В приведенной выше таблицеToNumber(A)Попробуйте поставить параметры перед сравнениемAПреобразовать в числа.ToPrimitive(A)установить параметрAПреобразовать в примитивное значение (Primitive).

12.1 + {}а также{} + 1Что такое выход?

Благодаря вышеуказанному обучению, когда объект добавляется с другими элементами, объект будет вызыватьtoPrimitiveПреобразовать в исходное значение:

  1. воплощать в жизньtoPrimitive, не прошелPreferredType,methodNamesдля[valueOf, toString]
  2. воплощать в жизнь({}).valueOf, который возвращает сам объект{}, а не исходное значение
  3. Продолжать({}).toString(),вернуть"[object Object]", возвращаемый результат является исходным значением, преобразование завершается

В настоящее время1 + {}, правая сторона естьstringтипа, будет1провестиToString()превратиться в"1", окончательная конкатенация строк, результат"1[object Object]"

Уведомление:{} + 1И результаты вывода1 + {}Это то же самое?

{}существуетJavaScript, не только как определения объектов, но и как определения блоков кода.jsдвигатель будет{} + 1анализируется в1 кодовый блок и 1 +1, окончательный вывод1

Отвечать

1[object Object]
1

13. Что получится, если сложить [] и {}?

[] + {}

Массивы — это специальные объекты, которые нужно вызыватьtoPrimitive, преобразуется в исходное значение

  • воплощать в жизньtoPrimitive, не прошелPreferredType,methodNamesдля[valueOf, toString]
  • воплощать в жизнь[].valueOf, который возвращает сам массив
  • воплощать в жизнь[].toString, который возвращает пустую строку''

Пустые объекты не вдаются в детали.

Отвечать

"[object Object]"

[] + []

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

Отвечать

""

{} + []

похожий на{} + 1,{} + []эквивалентно{}; + [], один юань+заствили""неявно преобразуется в0, окончательный результат0

Отвечать

0

{} + {}

На этот вопрос я сначала объявлю ответ, а затем расскажу о своем вопросе.

Отвечать

[object Object][object Object]

сомневаться

ЗачемJavaScriptДвигатель не повернул переднюю{}Интерпретируется как блок кода?

Дружеское напоминание: потому что{}Его можно интерпретировать в виде блока кода, есть несколько моментов, на которые стоит обратить внимание, например:

  • При вызове метода для пустого объекта:{}.toString()сообщит об ошибке
  • Когда функция стрелки возвращает объект:let getTempItem = id => { id: id, name: "Temp" }сообщит об ошибке

14. Можно ли гибко использовать parseInt и parseFloat?

  1. parseInt: Начните с числового класса и возвращайтесь к исходному числу, пока он не увидит нечисловой класс. (десятичная точка также является незначащим числом)
parseInt('123x') -> 123
parseInt('-023x') -> -23
parseInt('1.1') -> 1
parseInt('-abc') -> NaN
parseInt('x123') -> NaN
  1. parseInt(string, radix)Есть еще второй параметрradixУказывает основание числа для анализа, значение равно2~36(по умолчанию10)
  2. parseFloatа такжеparseIntАналогично, за исключением того, что он возвращает число с плавающей запятой. Начиная с числового класса, обратите внимание, что нечисловой класс, за исключением первой точки, является отсечкой, возвращающей предыдущее число.

Чистый красный вопрос: ['1', '2', '3']. Карта (Парсент)

Этот чистый красный вопрос исследуетparseIntЕсть два параметра.mapПереданная функция может быть выполнена с тремя параметрами:

// ele   遍历的元素
// index 遍历的元素索引
// arr   数组
arr.map(function(ele, index, arr){})

['1','2','3'].map(parseInt) эквивалентно выполнению следующих трех процессов:

parseInt('1', 0, ['1','2','3'])
parseInt('2', 1, ['1','2','3'])
parseInt('3', 2, ['1','2','3'])
  • parseInt('1', 0, ['1','2','3']): когда основание равно 0, по умолчанию принимает 10 и, наконец, возвращает 1.
  • parseInt('2', 1, ['1','2','3']): основание равно 2~36, возвращает NaN
  • parseInt('3', 2, ['1','2','3']): значение системы счисления равно 2, двоичный код включает только 0, 1 и возвращает NaN.

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

valueOfПриложения

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