каталог
Чем отличается передок без закидывания от соленой рыбы?
2 Предисловие
В процессе проверки JavaScript вы можете столкнуться с:
-
null
а такжеundefined
разница? -
addEventListener
функция?
Такие разные вопросы илиa == 1 && a == 2
Такой интересный вопрос.
Классифицируйте их по основам JavaScript и опишите их все в этой статье.
При этом будет более десятка простых вопросов для отработки рук.
Три широко используемых API DOM
можно использоватьdocument
илиwindow
API элемента для управления самим документом или получения подклассов документа (различных элементов на веб-странице).
// 获取元素
const node = document.getElementById(id); // 或者 querySelector(".class|#id|name");
// 创建元素
const heading = document.createElement(name); // name: p、div、h1...
heading.innerHTML = '';
// 添加元素
document.body.appendChild(heading);
// 删除元素
document.body.removeChild(node);
Пример:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>DOM 操作</title>
<style>
div {
border: 1px solid #ccc;
padding: 50px;
width: 100px;
}
</style>
</head>
<body>
<div id="dom1">元素 1</div>
<div class="dom2">元素 2</div>
<button class="btn">点我</button>
<script>
(function() {
const btn = document.querySelector('.btn');
// 注册点击事件
btn.onclick = function() {
const dom1 = document.getElementById('dom1');
// 第一种添加元素
const newDom1 = document.createElement('p');
newDom1.innerHTML = '<a href="https://github.com/LiangJunrong/document-library">jsliang 的文档库</a>';
dom1.appendChild(newDom1);
// 第二种添加元素
const newDom2 = document.createElement('ul');
newDom2.innerHTML = `
<li>aaa</li>
<li>bbb</li>
`;
document.body.appendChild(newDom2);
// 移除元素
const dom2 = document.querySelector('.dom2');
document.body.removeChild(dom2);
}
})()
</script>
</body>
</html>
Четыре различия между null и undefined
Сценарии использования разбиты следующим образом:
-
null
:
-
Number(null)
получать0
. - В качестве аргумента функции это означает, что аргумент функции не является объектом.
- как конец цепочки прототипов объектов.
Object.prototype.__proto__ === null
.
-
undefined
:
-
Number(undefined)
получатьNaN
. - Переменная объявлена, но ей не присвоено значение, равное
undefined
. - При вызове функции соответствующий параметр не предоставляется, также
undefined
. - Объекту не присваивается значение, значение этого свойства равно
undefined
. - Функция не имеет возвращаемого значения, она возвращает значение по умолчанию
undefined
.
Пять потоков событий
Что такое поток событий. Поток событий описывает порядок, в котором события поступают со страницы.DOM 2
Поток событий уровня включает следующие этапы.
- этап захвата событий
- на целевой стадии
- фаза всплытия события
Как сначала сделать пузырь события, а потом поймать:
существуетDOM
В стандартной событийной модели сначала отлавливается, а потом всплывает. Однако, если вы хотите сначала добиться эффекта всплытия, а затем захвата, для одного и того же события отслеживайте захват и всплытие, соответствующие соответствующим функциям обработки, прослушивайте событие захвата и приостанавливайте выполнение до тех пор, пока не будет захвачено всплывающее событие, а затем выполнить захват.
5.1 addEventListener
addEventListener
метод регистрирует указанный слушатель вEventTarget
On, когда объект инициирует указанное событие, будет выполнена указанная функция обратного вызова.
addEventListener
Целью события может быть элемент в документеElement
,Document
а такжеWindow
или любой другой объект, который поддерживает события (например,XMLHttpRequest
).
Справочная документация: [EventTarget.addEventListener - MDN][developer.Mozilla.org/this-cn/docs/…]
- грамматика:
target.addEventListener(type, listener, options/useCapture)
-
type
: строка, представляющая тип события прослушивания. -
listener
: Отслеживаемое событие запускается и получает объект уведомления о событии. -
options
: обозначение, связанное сlistener
Необязательный объект параметра для свойства. Необязательные значенияcapture
(Фаза захвата события распространяется на этот триггер),once
(существуетlistener
После добавления значение вызывается не более одного раза),passive
(Установить какtrue
времяlistener
никогда не звониpreventDefault()
). -
useCapture
: В дереве DOM зарегистрированыlistener
, следует ли предшествовать элементу под нимEventTarget
назовите этоlistener
.
addEventListener
Третий параметр включает всплытие и захват, дляtrue
захвачен, дляfalse
при бульканье.
или объект
{ passive: true }
, дляSafari
Браузер, используемый при отключении/включении прокрутки
- Пример
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>监听器</title>
</head>
<body>
<table id="outside">
<tr><td id="t1">one</td></tr>
<tr><td id="t2">two</td></tr>
</table>
<script>
(function() {
// 添加函数
const modifyText = (text) => {
const t2 = document.querySelector('#t2');
if (t2.firstChild.nodeValue === text) {
t2.firstChild.nodeValue = 'two';
} else {
t2.firstChild.nodeValue = text;
}
}
// 给 Table 添加事件监听器
const element = document.querySelector('#outside');
element.addEventListener('click', function() { modifyText('four') }, false);
})()
</script>
</body>
</html>
Как и выше, этот пример просто реализует щелчокtwo
переключиться наfour
, нажмитеfour
переключиться наtwo
Эффект.
5.2 Принцип
Захват событий и пузырь событийНетскейп(Нетскейп) иIEправильноDOM
Описание порядка, в котором произошли события.
НетскейпдуматьDOM
Полученное событие должно быть сначалаwindow
, затем кdocument
, затем спускаемся слой за слоем, и, наконец, конкретный элемент получает событие, т.е.захват событий.
IEдумаю, чтоDOM
События должны сначала приниматься конкретными элементами, затем слой за слоем, а затемdocument
, наконец, прибылwindow
,Прямо сейчасвсплывающее окно события.
наконецW3CОбе схемы унифицированы:DOM
События делятся на две фазы: захват событий и всплывающая всплывающая подсказка.
Когда элемент щелкнут, первая фаза захвата события,window
Событие сначала принимается, затем захватывается слой за слоем и, наконец, принимается конкретным элементом; затем конкретный элемент всплывает слой за слоем, покаwindow
Получать события.
так:
-
всплывающее окно события: когда событие привязано к целевому элементу, событие будет срабатывать в его родительском элементе по очереди (при условии, конечно, что родительский элемент также имеет событие с таким же именем, например, и дочерний элемент, и исходный элемент). родительский элемент привязан к диапазону
click
Событие запускает родительский элементclick
). - захват событий: Вопреки пузыриться, он будет передан от верхнего слоя до нижнего слоя.
5.3 Случаи
Пример с пользовательскими событиями:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>自定义事件</title>
</head>
<body>
<ul class="ul">
<li class="li">
<button class="btn">点我</button>
</li>
</ul>
<script>
window.onload = function() {
const myEvent = document.createEvent('CustomEvent');
myEvent.initEvent('myEvent', true, true);
const btn = document.querySelector('.btn');
btn.addEventListener('myEvent', function(e) {
console.log('button');
})
const li = document.querySelector('.li');
li.addEventListener('myEvent', (e) => {
console.log('li');
})
const ul = document.querySelector('.ul');
li.addEventListener('myEvent', (e) => {
console.log('ul');
})
document.addEventListener('myEvent', (e) => {
console.log('document');
})
window.addEventListener('myEvent', (e) => {
console.log('window');
})
setTimeout(() => {
btn.dispatchEvent(myEvent);
}, 2000);
};
</script>
</body>
</html>
Следующий порядок вывода Chrome:button
-> li
-> ul
-> document
-> window
Если это захват, то все наоборот.
5.4 Практические вопросы
нажмите одинinput
события, которые запускаются последовательно
const text = document.getElementById('text');
text.onclick = function (e) {
console.log('onclick')
}
text.onfocus = function (e) {
console.log('onfocus')
}
text.onmousedown = function (e) {
console.log('onmousedown')
}
text.onmouseenter = function (e) {
console.log('onmouseenter')
}
Правильный порядок:onmouseenter -> onmousedown -> onfocus -> onclick
.
Если вы добавитеonmouseup
,То есть:
onmouseenter -> onmousedown -> onfocus -> onmouseup -> onclick
5.5 Перестаньте пузыриться
event.stopPropagation();
btn.addEventListener('myEvent', function(e) {
console.log('button');
event.stopPropagation();
})
Предотвращая всплытие, программа будет выводить толькоbutton
, вместо того, чтобы продолжать выводитьli
Ждать.
5.6 Разница между onmouseover и onmouseenter
Оба срабатывают при движении, ноonmouseover
будет срабатывать несколько раз, в то время какonmouseenter
Срабатывает только при входе.
5.7 Популярная наука
Не все события всплывают, например:
onblur
onfocus
onmouseenter
onmouseleave
Шесть различий между typeof и instanceof
-
typeof
: Обнаружение типа переменной, кроме базового типаnull
За исключением функции, он может нормально отображаться как соответствующий тип, а ссылочный тип будет отображаться как функция, кроме функции.function
, остальные отображаются какobject
. -
instanceof
Он в основном используется для определения того, находится ли объект-прототип конструктора в цепочке прототипов объекта.
typeof
будуnull
Ошибка отображения является исторической ошибкой,typeof null
выводobject
, так как ранняя версия JavaScript была 32-битной системой, по соображениям производительности используйте низкоуровневую информацию о типах переменных хранения,000
Однако начало представляет объектnull
представлен как все нули, поэтому он ошибочно оценивает какobject
.
а такжеObject.prototype.toString.call()
Делайте переменные суждения.
Подробности можно увидеть:JavaScript — переменные
Семь одно предложение, описывающее это
Для функций объект, указывающий на последнюю вызывающую функцию, является внутренним объектом, автоматически генерируемым при запуске функции, и может использоваться только внутри функции; для глобальных объектовthis
направлениеwindow
.
Восемь позиций JS
-
clientHeight
: Указывает высоту видимой области, исключаяborder
и полоса прокрутки -
offsetHeight
: Указывает высоту видимой области, включаяborder
и полоса прокрутки -
scrollHeight
: Указывает высоту всех областей, включая ту часть, которая скрыта из-за прокрутки. -
clientTop
: указывает границуborder
толщина, как правило, в случае неуказанного0
-
scrollTop
: Высота, которую нужно скрыть после прокрутки, получить объект относительноoffsetParent
заданные свойством родительские координаты (позиционированные элементы CSS илиbody
элемент) высота от вершины.
Перетаскивание девяти JS
- пройти через
mousedown
,mousemove
,mouseup
реализация метода - через HTML5
Drag
а такжеDrop
выполнить
10 setTimeout реализует setInterval
Это альтернативная точка знаний, Первоначально предполагалось, что она будет классифицирована как серия рукописных исходных кодов, но я слишком много думаю.low
Теперь без карт, переходим к основному ряду:
const say = () => {
// do something
setTimeout(say, 200);
};
setTimeout(say, 200);
Очистить этот таймер:
let i = 0;
const timeList = [];
const say = () => {
// do something
console.log(i++);
timeList.push(setTimeout(say, 200));
};
setTimeout(say, 200);
setTimeout(() => {
for (let i = 0; i < timeList.length; i++) {
clearTimeout(timeList[i]);
}
}, 1000);
Одиннадцать достичь сна
Как следует, для достижения1000
Сделайте что-нибудь еще через миллисекунды:
const sleep = time => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(time);
}, time);
});
};
sleep(1000).then((res) => {
console.log(res);
});
12 Контекст выполнения
12.1 Типы контекста выполнения
В JavaScript существует 3 типа контекста выполнения:
-
глобальный контекст выполнения: это контекст по умолчанию или базовый, любой код не внутри функции находится в глобальном контексте. Он делает две вещи: создает глобальный
window
объект (в случае браузера) и установитьthis
Значение равно этому глобальному объекту. В программе существует только один глобальный контекст выполнения. - контекст выполнения функции: Всякий раз, когда вызывается функция, для этой функции создается новый контекст. Каждая функция имеет свой собственный контекст выполнения, но создается при вызове функции. Контекстов функций может быть любое количество. Всякий раз, когда создается новый контекст выполнения, он выполняет серию шагов в определенном порядке.
-
Контекст выполнения функции Eval: выполнить на
eval
Код внутри функции также будет иметь свой контекст выполнения, но поскольку разработчики JavaScript не часто используютeval
, поэтому я не буду обсуждать это здесь.
12.2 Стек выполнения
Стек выполнения, также известный как «стек вызовов» в других языках программирования, представляет собойLIFO
Стек структур данных (последний вошел, первый вышел), используемый для хранения всех контекстов выполнения, созданных при выполнении кода.
Когда движок JavaScript впервые встречает ваш сценарий, он создает глобальный контекст выполнения и помещает его в текущий стек выполнения. Всякий раз, когда механизм встречает вызов функции, он создает новый контекст выполнения для этой функции и помещает его на вершину стека.
Механизм выполняет функции, контекст выполнения которых находится на вершине стека. Когда выполнение функции завершается, контекст выполнения извлекается из стека, и поток управления переходит к следующему контексту в текущем стеке.
let a = 'Hello World!';
function first() {
console.log('Inside first function');
second();
console.log('Again inside first function');
}
function second() {
console.log('Inside second function');
}
first();
console.log('Inside Global Execution Context');
Тринадцать функциональных программ
Функциональное программирование (сокращенно FP).
Функциональное программирование: благодаря разделению кода объектно-ориентированного программирования каждая функция становится независимой, что позволяет добиться независимости функций и легкого повторного использования.
Пример: преобразование кода
['john-reese', 'harold-finch', 'sameen-shaw']
// 转换成
[{name: 'John Reese'}, {name: 'Harold Finch'}, {name: 'Sameen Shaw'}]
Преобразуйте приведенный выше код.
const arr = ['john-reese', 'harold-finch', 'sameen-shaw'];
const newArr = [];
for (let i = 0, len = arr.length; i < len ; i++) {
let name = arr[i];
let names = name.split('-');
let newName = [];
for (let j = 0, naemLen = names.length; j < naemLen; j++) {
let nameItem = names[j][0].toUpperCase() + names[j].slice(1);
newName.push(nameItem);
}
newArr.push({ name : newName.join(' ') });
}
return newArr;
В этом коде есть 2 части:
- Разбивает строки в массиве и превращает строки в имена людей.
john-reese -> John Reese
- Преобразование массива в объект.
['John Reese'] -> [{ name: 'John Reese' }]
Таким образом, мы можем напрямую изменить:
/**
* @name 改变人名展示方式
* @param {array} arr 需要改变的数组
* @param {string} type 支持不同格式的人名
*/
const changeName = (arr, type) => {
return arr.map(item => item.split(type).map(name => name[0].toUpperCase() + name.slice(1)).join(' '));
};
/**
* @name 数组改变成对象
* @param {array} arr 需要改变的数组
* @param {string} key 对应变成什么字段
* @return {object} 返回改变后的对象
*/
const arrToObj = (arr, key) => {
return arr.map(item => ({ [key]: item }));
};
const result = arrToObj(changeName(['john-reese', 'harold-finch', 'sameen-shaw'], '-'), 'name');
console.log(result); // [ { name: 'John Reese' }, { name: 'Harold Finch' }, { name: 'Sameen Shaw' } ]
Привет, это не просто инкапсуляция функций? Вообще говоря, инкапсулируется код, встречающийся в работе более 2 раз.
Функциональное программирование — это извлечение и инкапсуляция функций, которые можно извлечь.
Кажется, здесь постигли истину,jsliangЯ не понял определение в деталях, надеюсь, оно не вводит в заблуждение.
13.1 Особенности функционального программирования
- Функции являются гражданами первого класса. Вы можете воспользоваться этим, чтобы поддержать извлечение во внешний мир.
- объявить что-то сделать. Функциональное программирование в основном определяет, что должна делать функция, а не то, как она это делает.
- легкая сборка мусора. Переменные внутри функции удобны для сборки мусора, переменных не будет слишком много, и пользователю не нужно много определений.
- Данные неизменны. Функциональное программирование требует, чтобы все данные были неизменяемыми.Если вам нужно изменить объект, вы должны создать его, а затем изменить, а не загрязнять исходные данные.
- нет статуса. Одна и та же функция возвращает одни и те же выходные данные для одних и тех же входных данных, независимо от изменений внешнего состояния, независимо от того, когда она выполняется.
- Нет побочных эффектов. Функцию A следует использовать только для завершения ее реализации, а не для изменения внешними изменениями, чтобы, когда она завершит выполнение, ее внутренние данные можно было повторно использовать. И он не изменяет переданные параметры.
Обратите внимание на передачу эталонных значений (Object, Array), и постарайтесь не загрязнять входящие данные.
13.2 Чистые функции
Понятие чистой функции имеет 2 пункта:
-
Не зависит от внешнего состояния (без гражданства): текущий результат функции не зависит от глобальных переменных,
this
указатель,IO
операция и т.д. - Нет побочных эффектов (данные без изменений): Не изменяйте глобальные переменные и входные параметры.
преимущество:
- Легко тестировать и оптимизировать
- кешируемость
- самодокументирующийся
- меньше ошибок
14 прогрессивных веб-приложений (PWA)
Прогрессивные веб-приложения (PWA) — это концепция, представленная Google в конце 2015 года. В основном веб-приложение, но выглядит и работает как нативное приложение. Веб-сайты, поддерживающие PWA, могут предлагать такие функции, как автономная работа, push-уведомления и доступ к оборудованию устройства.
14.1 Преимущества
- меньше и быстрее: прогрессивные веб-приложения намного меньше нативных приложений. Их даже не нужно устанавливать. Это они не тратят место на диске и загружаются очень быстро.
- Отзывчивый интерфейс: веб-страницы, поддерживаемые PWA, могут автоматически адаптироваться к различным размерам экрана. Это может быть телефон, планшет, настольный компьютер или ноутбук.
- Нет необходимости обновлять: Большинство мобильных приложений требуют регулярных еженедельных обновлений. Как и обычные веб-сайты, PWA всегда загружают последнюю обновленную версию всякий раз, когда происходит взаимодействие с пользователем, и не требуют одобрения приложения или магазина игр.
- Экономически эффективным: нативные мобильные приложения необходимо разрабатывать отдельно для устройств Android и iOS, а стоимость разработки очень высока. С другой стороны, PWA имеют ту же функциональность, но за небольшую часть предыдущей цены и с низкими затратами на разработку.
- SEO-преимущество: PWA обнаруживаются поисковыми системами и загружаются очень быстро. Как и на других веб-сайтах, их ссылками также можно делиться. Обеспечьте хороший пользовательский опыт и результаты, повышение рейтинга SEO.
- Автономная функция: к PWA можно получить доступ в автономном режиме или при низком уровне интернет-соединения благодаря поддержке Service Worker API.
- безопасность: PWA доставляется через соединение HTTPS и защищает данные пользователя при каждом взаимодействии.
- Отправить уведомление: Благодаря поддержке push-уведомлений PWA легко взаимодействуют с пользователями и обеспечивают отличный пользовательский интерфейс.
- обойти магазин приложений: если нативному приложению требуется какое-либо новое обновление, ему требуется несколько дней одобрения в App Store, и есть вероятность его отклонения или запрета.В этом аспекте PWA имеет свои уникальные преимущества и не требует поддержки App Store. Обновленные версии могут быть загружены непосредственно с веб-сервера без одобрения App Store.
- Нулевая установка: во время просмотра PWA имеют свои собственные значки на телефонах и планшетах, как и мобильные приложения, но без длительного процесса установки.
14.2 Недостатки
- Меньший доступ к системным функциям: в настоящее время PWA имеют ограниченный доступ к собственным системным функциям, чем собственные приложения. Также не все браузеры поддерживают его полную функциональность, но, вероятно, в ближайшем будущем он станет новым стандартом разработки.
- Большинство Android, несколько iOS: В настоящее время больше поддержки исходит от Android. Только часть его обеспечивается системой iOS.
- нет критериев проверки: PWA не требуют проверки нативных приложений в магазине приложений, что может ускорить процесс, но им не хватает преимуществ продвижения в магазине приложений.
15 Нормализация
CommonJS
Технические характеристики,AMD
Технические характеристики,CMD
Технические характеристики,ES6 Modules
Все эти четыре спецификации представляют собой интерфейсный стандартизированный контент, так в чем же между ними разница?
До них мы прошли:
- Функция — это модуль.
function fn() {}
- Объект — это модуль.
let obj = new Object({ ... })
- Функция немедленного выполнения (IIFE).
(function() {})()
15.1 Спецификация CommonJS
После этого естьCommonJS
спецификация, на самом делеCommonJS
Мы видели многое, т.Node
Набор из:
- Экспорт:
module.exports = {}
,exports.xxx = 'xxx'
- импорт:
require(./index.js)
- Метод поиска: найти, есть ли в текущем каталоге файл, если нет, найти текущий каталог
node_modules
документ. Хватит, всплывающий запрос, всегда обращающийся к системеnpm
Поиск по каталогу.
Его особенности:
- Весь код выполняется в рамках модуля, не загрязняя другие файлы.
-
require
Полученное значение является копией значения, то есть вы ссылаетесь на переменные в других JS-файлах, и операция модификации не повлияет на другие файлы.
Есть у него и свои недостатки:
- прикладной уровень. существует
index.html
сделано вvar index = require('./index.js')
Операция сообщает об ошибке, поскольку в конечном итоге она выполняется в фоновом режиме и может бытьindex.js
Цитироватьindex2.js
Сюда. - Проблема с синхронной загрузкой.
CommonJS
В спецификации модули загружаются синхронно, т.index.js
загрузкаindex2.js
,еслиindex2.js
Если вы застряли, вам придется долго ждать.
15.2 Технические характеристики AMD
зачемAMD
Технические характеристики?
отвечать:CommonJS
Спецификация бесполезна:
- Применимые клиенты
- Ожидание загрузки (проблема синхронной загрузки).
Так что же он делает?
Модули могут загружаться асинхронно.AMD
даAsynchronous Module Definition
Сокращение от «определения асинхронного модуля», запомните этоasync
Просто знайте, что это асинхронно.
15.3 Спецификации CMD
CMD (Общее определение модуля) — это стандарт, рекомендованный seajs, CMD зависит от ближайшего, а затем снова используйте его.require
.
Самая большая разница между AMD и CMD заключается в том, что время выполнения зависимых модулей отличается.Обратите внимание, что время или метод загрузки не отличаются.Оба являются модулями асинхронной загрузки.
15.4 Спецификация модулей ES6
- Экспорт:
export a
export { a }
export { a as jsliang }
export default function() {}
- импорт:
import './index'
import { a } from './index.js'
import { a as jsliang } from './index.js'
import * as index from './index.js'
Функции:
-
export
команда иimport
Команды могут появляться в любом месте модуля, если они находятся на верхнем уровне модуля. Если он находится на уровне блока, будет сообщено об ошибке, потому что в условном блоке кода статическая оптимизация не может быть выполнена, что нарушает первоначальный замысел дизайна модуля ES6. -
import
Команда имеет эффект подъема и будет поднята на голову всего модуля, который выполняется первым.
а такжеCommonJS
разница:
-
CommonJS
модули загружаются во время выполнения,ES6 Modules
это интерфейс вывода времени компиляции -
CommonJS
Вывод — это копия значения;ES6 Modules
Вывод представляет собой ссылку на значение, и изменения внутри экспортируемого модуля повлияют на изменение ссылки. -
CommonJs
Импортированный путь к модулю может быть выражением, поскольку он используетrequire()
метод; иES6 Modules
может быть только строка -
CommonJS this
указывает на текущий модуль,ES6 Modules
изthis
направлениеundefined
-
ES6 Modules
Этих переменных верхнего уровня нет в:arguments
,require
,module
,exports
,__filename
,__dirname
Шестнадцать принципов компиляции Babel
-
babylon
БудуES6/ES7
Код разбирается наAST
-
babel-traverse
правильноAST
Выполните обходной перевод, чтобы получить новыйAST
- новый
AST
пройти черезbabel-generator
Перевести вES5
этот кусок словjsliangЭто не слишком глубоко, это легко понять, если вы просто поймете это:
- Форма, состоящая из черных и белых танграмм, разделенных на части (
ES6/ES7
анализируется вAST
) - Замените эти детали на цветные (
AST
скомпилировать получить новыйAST
) - Соберите цветные детали в новые формы (
AST
Перевести вES5
)
Семнадцать вопросов
17.1 Общие API для массивов
-
push
: добавить элемент в конец массива -
unshift
: добавить элементы в начало массива -
pop
: удалить элемент с конца массива -
shift
: удалить элемент из головы массива -
splice
: удалить элемент массива -
slice
: обрезать элементы массива -
indexOf
: найти первое вхождение элемента -
lastIndexof
: найти последнее вхождение элемента -
findIndex
: Найдите позицию, в которой элемент появляется впервые. -
forEach
: перебирать элементы -
map
: перебирать элементы -
filter
: элемент фильтра -
some
: содержит элемент -
every
: Все элементы соответствуют элементу -
includes
: проверить, включен ли элемент -
concat
: объединить элементы -
join
: объединить элементы в строки -
toString
: становится строкой -
sort
: порядок элементов
17.2 Общие API-интерфейсы DOM
- Получать
- Создайте
- Добавить к
- удалять
// 获取元素
const node = document.getElementById(id); // 或者 querySelector(".class|#id|name");
// 创建元素
const heading = document.createElement(name); // name: p、div、h1...
heading.innerHTML = '';
// 添加元素
document.body.appendChild(heading);
// 删除元素
document.body.removeChild(node);
17.3 Дедупликация массива
Дедупликация массива — часто упоминаемый момент:
const arr = [1, 1, 2, 3, 3];
// 期望得到:[1, 2, 3]
// 方法一:for 配合新数组截取
const newArr1 = [];
for (let i = 0; i < arr.length; i++) {
if (!newArr1.includes(arr[i])) {
newArr1.push(arr[i]);
}
}
console.log('newArr1:', newArr1);
// 方法二:使用 Set
const newArr2 = [...new Set(arr)];
console.log('newArr2:', newArr2);
// 方法三:使用 filter
const newArr3 = arr.filter((item, index) => arr.lastIndexOf(item) === index);
console.log('newArr3:', newArr3);
Интересный вопрос из интервью: не используйте массивыAPI
Выполнить дедупликацию.
Примечание: нельзя использовать
push
,indexOf
ЖдатьAPI
17.4 Оцифрованные суммы
- Метод 1: Обход методом грубой силы
const num = String(1234567890);
let result = '';
for (let i = num.length - 1; i >= 0; i--) {
if (i !== num.length - 1 && i % 3 === 0) {
result = num[i] + ',' + result;
} else {
result = num[i] + result;
}
}
console.log(result);
- Способ 2: API-навыки
console.log(
String(1234567890).split('').reverse().reduce((prev, next, index) => (index % 3) === 0 ? next + ',' + prev : next + prev)
);
- Способ 3: API-навыки
console.log(
(1234567890).toLocaleString('en-US')
);
- Способ 4: регулярные выражения
String(1234567890).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
17.5 Проблемы обхода
Каков результат массива после выполнения следующего кода?
let array = [ , 1, , 2, , 3];
array = array.map((i) => ++i)
- А:
[ , 2, , 3, , 4]
- Б:
[NaN, 2, NaN, 3, NaN, 4]
- С:
[1, 2, 1, 3, 1, 4]
- Д:
[null, 2, null, 3, null, 4]
Ответ: А
объяснять:
-
forEach()
,filter()
,reduce()
,every()
а такжеsome()
пропустит вакансию. -
map()
пропустит пробелы, но сохранит значение -
join()
а такжеtoString()
будет рассматривать вакансии какundefined
,а такжеundefined
а такжеnull
будет рассматриваться как пустая строка.
17.6 setTimeout
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
Каков результат выполнения приведенного выше кода?
- А: 5 5 5 5 5
- Б: 0 0 0 0 0
- С: 0 1 2 3 4
- Д: 1 2 3 4 5
Ответ: А
Разобрать:
-
var i
существуетfor
При использовании в , это вызовет переменное загрязнение, что приведет к глобальному обходуi
,этоi
беги до конца,5
-
setTimeout
это задача макроса, вscript
Эта задача макроса выполняется после завершения выполнения, поэтому собранныйi
да5
- Окончательный результат 5
5
17.7 requestAnimationFrame
for (let i = 0; i < 5; i++) {
requestAnimationFrame(() => {
console.log(i);
});
}
Результат выполнения приведенного выше кода:
- А: 1 2 3 4 5
- Б: 0 1 2 3 4
- С: 4 4 4 4 4
- Д: 5 5 5 5 5
Ответ: Б
Разобрать:
-
let i
Сделатьfor
Формирует область действия на уровне блока. -
requestAnimationFrame
похожий наsetTimeout
, но его можно рассматривать как микрозадачу, которая представляет собой метод, вызываемый после выполнения очереди микрозадач и до выполнения рендеринга пользовательского интерфейса. - Поэтому этот вопрос не касается
requestAnimationFrame
будет собиратьi
, ноlet
Проблема блочной области видимости образуется, если изменить ее наvar i
, по-прежнему выводить 55
.
17.8 Временная зона нечувствительности
1. Что выводит следующий код?
let a = 1;
let test = function() {
console.log(a);
a++;
}
test();
2. Что выводит следующий код?
let a = 1;
let test = function() {
console.log(a);
let a = 2;
a++;
}
test();
Отвечать:
Вывод первого вопроса:1
Вывод второго вопроса:Uncaught ReferenceError: Cannot access 'a' before initialization
Разобрать:
Причина в том, что тот жеblock
середина,let
Если она будет переопределена позже, на переменную нельзя будет сослаться раньше. При этом значение вложенного внешнего слоя взять нельзя.
17.9 Вывод результата печати
function sayHi() {
console.log(name);
console.log(age);
var name = "Lydia";
let age = 21;
}
sayHi();
Вывод приведенного выше кода?
Ответ: не определено, ошибка
Разобрать:
Этот вопрос меняется, чтобы ясно видеть:
function sayHi() {
var name; // 变量提升 - 变量声明
console.log(name); // undefined
console.log(age); // let 存在暂时性死区,不会变量提升
name = "Lydia"; // 变量提升 - 变量赋值
let age = 21;
}
sayHi();
17.10 Вывод результата печати
function myFunc() {
console.log(a);
console.log(func());
var a = 1;
function func() {
return 2;
}
}
myFunc();
Подскажите, пожалуйста, что на выходе?
Отвечать:undefined
2
Разбор: не сложный, без разбора
17.11 Event Loop
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
Вывод приведенного выше кода?
Ответы и анализ:
Первая тема:var
существуетfor
В синхронном коде есть переменное загрязнениеfor
После завершения выполнения снова выполните задачу макроса.setTimeout
, найти текущийi
оба становятся3
, поэтому вывод3、3、3
Вторая тема:let
существуетfor
Область видимости на уровне блока будет сформирована вi
является новым значением, и каждое значение существует в области блока внутри цикла, поэтому вывод0、1、2
17.12 Вывод результата печати
let date = new Date();
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(new Date - date, i); // 1
}, 1000);
}
console.log(new Date - date, i); // 2
Подскажите, пожалуйста, что на выходе?
Отвечать:
0 5
1001 5
1004 5
1005 5
1006 5
1007 5
Анализ: тема сначала переходит к задаче макросаscript
, поэтому определитеdate
После этого выполните строку, закомментированную как 2console
.
Затем 5 макрозадач, все таймерыsetTimeout
, поэтому он будет выполнен после, вывод:1000 5
, но таймер не обязательно пунктуален, поэтому может быть1001
,1002
или что-то другое.
17.13 Сделать == 1 && a == 2 истинным
Попробуйте закодировать так, чтобы:if(a == 1 && a == 2 && a == 3) {}
Это положение соответствует действительности.
- метод первый
Во время преобразования типов мы знаем, как объекты преобразуются в примитивные типы данных. если развернут[Symbol.toPrimitive]
, то возвращаетсяSymbol.toPrimitive
Возвращаемое значение.
Конечно, мы также можем развернуть эту функцию вvalueOf
илиtoString
На интерфейсе эффект тот же.
//利用闭包延长作用域的特性
let a = {
[Symbol.toPrimitive]: (function () {
let i = 1;
return function () {
return i++;
}
})()
}
- Способ второй
использоватьObject.defineProperty
существуетwindow/global
определено вышеa
собственность, получитьa
свойство, оно будет называтьсяget
let val = 1;
Object.defineProperty(window, 'a', {
get: function() {
return val++;
}
});
- Способ третий
var a = [1, 2, 3];
a.join = a.shift;
массивtoString
метод возвращает строку, состоящую из значений каждого элемента массиваtoString()
Возвращаемое значение называетсяjoin()
Конкатенации методов (разделяются запятыми).
Поэтому мы можем повторноjoin
метод. Возвращает первый элемент и удаляет его.
Еще восемнадцать
Есть много базовых знаний или тем,jsliangУ меня нет сил добавлять их по одному, и я стараюсь вставлять в статью исходный текст.
- 43 вопроса о собеседовании по JavaScript для вас[Рекомендация по прочтению: 1 час]
Эта статья неплохая,jsliangВ первый раз, когда я сделал это, я все еще неправильно задавал вопросы, ха-ха.
Так что эта статья здесь, желаю друзьям поскорее найти нужноеOffer
.
библиотека документации jsliangЗависит отЛян ЦзюньронгиспользоватьCreative Commons Attribution-NonCommercial-ShareAlike 4.0 Международная лицензияЛицензия.
на основеGitHub.com/l ian Jun Ron…Создание работ выше.
Права на использование, отличные от разрешенных в настоящем Лицензионном соглашении, могут быть получены отCreative Commons.org/licenses/не…получено в.