привет всем, меня зовут Дерек
Сегодня я поговорю с вами об основных знаниях фронтенд-интервью. Осень и весна — сезоны смены работы. Надеюсь, эта статья поможет вам и поможет получить любимое предложение.
Основы интерфейса
браузер
- Механизмы кэширования браузера: сильный кэш против согласованного кэша и в чем разница?
- Связанные с хранилищем: для чего используются localstorage, sessionStorage, файлы cookie и т. д. и в чем различия?
- Что означают элементы на сетевой панели браузера, в основном период времени под таймингом? Что такое ТТФБ?
- Использовали ли вы производительность браузера и для чего он нужен?
- Принцип кроссдоменности, каковы методы реализации кроссдоменности?
- Что такое цикл событий в среде браузера? По сути, это еще и макрозадача, и микрозадача, как видитеэта статья
JavaScript
Примитивные типы данных и ссылочные типы данных
- Основные типы данных: Undefined, Null, Boolean, String, Number, Symbol
- Справочные типы данных: объект, массив, дата, регулярное выражение, функция
- Здесь можно рассмотреть typeof, instanceof; включая ручную реализацию следующих typeof и instanceof
// 实现typeof
function type(obj) {
return Object.prototype.toString.call(a).slice(8,-1).toLowerCase();
}
// 实现instanceof
function instance(left,right){
left=left.__proto__
right=right.prototype
while(true){
if(left==null)
return false;
if(left===right)
return true;
left=left.__proto__
}
}
Сеть прототипов
Поймите, что делает цепочка прототипов, а именно: экземпляры.proto=== Конструктор.прототип
Object.prototype.__proto__ === null // true
Function.prototype.__proto__ === Object.prototype // true
Object.__proto__ === Function.prototype // true
Вот над чем лучше подумать:
function F() {}
Object.prototype.b = 2;
F.prototype.a = 1;
var f = new F();
console.log(f.a) // 1
console.log(f.b) // 2
console.log(F.a) // undefined
console.log(F.b) // 2
Почему в приведенном выше коде F.a не определен?
function F() {}
Object.prototype.b = 2;
Function.prototype.a = 1;
var f = new F();
console.log(f.a) // undefined
console.log(f.b) // 2
console.log(F.a) // 1
console.log(F.b) // 2
Почему в приведенном выше коде f.a не определено?
function F() {}
F.prototype.a = 1;
var f1 = new F()
F.prototype = {
a: 2
}
var f2 = new F()
console.log(f1.a) // 1
console.log(f2.a) // 2
наследовать
Несколько способов наследования:
- Наследование цепочки прототипов:
недостаток:function SuperType() { this.name = 'Yvette'; this.colors = ['red', 'blue', 'green']; } SuperType.prototype.getName = function () { return this.name; } function SubType() { this.age = 18; } SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; let instance1 = new SubType(); instance1.colors.push('yellow'); console.log(instance1.getName()); console.log(instance1.colors); // ['red', 'blue', 'green', 'yellow'] let instance2 = new SubType(); console.log(instance2.colors); // ['red', 'blue', 'green', 'yellow'] -
- Когда наследование реализуется через прототип, прототип становится экземпляром другого типа, исходное свойство экземпляра становится текущим свойством прототипа, а свойство ссылочного типа прототипа будет общим для всех экземпляров. (значения ссылочного типа являются общими для всех экземпляров)
-
- При создании экземпляра подтипа невозможно передать аргументы конструктору супертипа, не затрагивая все экземпляры объекта.
- Наследование конструктора:
преимущество:function SuperType(name) { this.name = name; this.colors = ['red', 'blue', 'green']; } function SubType(name) { SuperType.call(this, name); } let instance1 = new SubType('draven'); instance1.colors.push('yellow'); console.log(instance1.colors); // ['red', 'blue', 'green', 'yellow'] let instance2 = new SubType('ben'); console.log(instance2.colors); // ['red', 'blue', 'green'] -
- Параметры могут быть переданы в суперкласс
-
- Решена проблема, связанная с тем, что значение ссылочного типа, содержащееся в прототипе, используется всеми экземплярами.
-
- Все методы определены в конструкторе, и повторное использование функции невозможно.
-
- Методы, определенные в прототипе супертипа, невидимы для подтипа.
- Наследование композиции:
недостаток:function SuperType(name) { this.name = name; this.colors = ['red', 'blue', 'green']; } SuperType.prototype.sayName = function () { console.log(this.name); } function SuberType(name, age) { SuperType.call(this, name); this.age = age; } SuberType.prototype = new SuperType() SuberType.prototype.constructor = SuberType let instance1 = new SuberType('draven', 25); instance1.colors.push('yellow'); console.log(instance1.colors); // ['red', 'blue', 'green', 'yellow'] instance1.sayName(); //draven let instance2 = new SuberType('ben', 22); console.log(instance2.colors); // ['red', 'blue', 'green'] instance2.sayName();//ben -
- В любом случае конструктор супертипа вызывается дважды: один раз при создании прототипа подтипа и один раз внутри конструктора подтипа.
-
- Параметры могут быть переданы в суперкласс
-
- Каждый экземпляр имеет свои свойства
-
- повторное использование функции
- Паразитическое наследование композиции, паразитное наследование композиции — наиболее рациональная парадигма наследования для ссылочных типов, использующая Object.create для оптимизации на основе наследования композиции:
function SuperType(name) { this.name = name; this.colors = ['red', 'blue', 'green']; } SuperType.prototype.sayName = function () { console.log(this.name); } function SuberType(name, age) { SuperType.call(this, name); this.age = age; } SuberType.prototype = Object.create(SuperType.prototype) SuberType.prototype.constructor = SuberType let instance1 = new SuberType('draven', 25); instance1.colors.push('yellow'); console.log(instance1.colors); //[ 'red', 'blue', 'green', 'yellow' ] instance1.sayName(); //draven let instance2 = new SuberType('ben', 22); console.log(instance2.colors); //[ 'red', 'blue', 'green' ] instance2.sayName();//ben - Наследование ES6:
class SuperType { constructor(age) { this.age = age; } getAge() { console.log(this.age); } } class SubType extends SuperType { constructor(age, name) { super(age); // 调用父类的constructor(age) this.name = name; } } let instance = new SubType(18, 'draven'); instance.getAge(); // 18 -
- Все методы, определенные внутри класса, не являются перечисляемыми. (Методы прототипов ES5 по умолчанию являются перечисляемыми)
Закрытие:
- Отверждение:
// 实现固定参数的curry
function add(a, b, c, d) {
return a + b + c + d
}
function curry(fn) {
const length = fn.length
let params = []
return function func() {
params = params.concat([].slice.call(arguments))
if (params.length === length) {
const res = fn.apply(null, params);
params = [];
return res;
} else {
return func;
}
}
}
const addCurry = curry(add);
console.log(addCurry(1, 2)(3, 4)); // 10
console.log(addCurry(2)(3)(4)(5)); // 14
// 实现随意参数的柯理化
function add() {
let params = [].slice.call(arguments);
function func() {
params = params.concat([].slice.call(arguments))
return func;
}
func.toString = () => {
return params.reduce((a, b) => {
return a + b;
}, 0);
}
return func;
}
console.log(add(1, 2)(3, 4)); // 10
console.log(add(2)(3)(4)(5)); // 14
- Стабилизация и троттлинг:
Функции защиты от сотрясений и дросселирования — это методы управления частотой срабатывания событий.
// 防抖
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result;
let nowTime = Date.now || function () {
return new Date().getTime();
};
const later = function () {
let last = nowTime() - timestamp;
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
if (!timeout) context = args = null;
}
}
};
return function () {
context = this;
args = arguments;
timestamp = nowTime();
let callNow = immediate && !timeout;
if (!timeout) timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
context = args = null;
}
return result;
};
};
// 节流
function throttle(fn, threshhold) {
let timeout
let start = new Date;
threshhold = threshhold || 160
return function () {
const context = this, args = arguments, curr = new Date() - 0
clearTimeout(timeout)//总是干掉事件回调
if (curr - start >= threshhold) {
fn.apply(context, args)
start = curr
} else {
//让方法在脱离事件后也能执行一次
timeout = setTimeout(function(){
fn.apply(context, args)
}, threshhold);
}
}
}
var/let/const
В этой части в основном рассматривается понимание let и var, продвижение переменных и т. д.
Каков результат выполнения следующего кода?
var foo = {n: 1};
var bar = foo;
foo.x = foo = {n: 2};
bar = ?
foo = ?
Результат вышеописанного выполнения:bar = {n:1,x:{n:2}}; foo={n:2};
a();
var a=3;
function a(){
alert(10)
}
alert(a)
a=6;
a()
Результат вышеописанного выполнения:10 3 error; Последняя ошибка связана с тем, что a не является функцией;
== и ===
Шаги неявного преобразования: Легко понять, что делается в случае сильного ожидания и двойного ожидания.
Сильное равенство (===) сначала сравнивает, одинаковы ли типы с обеих сторон, и если они разные, возвращает false напрямую; если типы одинаковы, это оценивается в соответствии с ==, давайте посмотрим на неявный преобразование, вызванное ==.
Неявное преобразование, вызванное двойным знаком равенства
1. Во-первых, проверьте, есть ли NaN до и после знака двойного равенства, Если есть NaN, он всегда будет возвращать false.
Во-вторых, посмотрите, есть ли логическое значение до и после двойного знака равенства.Если есть логическое значение, преобразуйте логическое значение в число. (ложь 0, правда 1)
3. Затем посмотрите, есть ли строка до и после знака двойного равенства, есть три ситуации:
1、对方是对象,对象使用toString()或者valueOf()进行转换;
2、对方是数字,字符串转数字;(前面已经举例)
3、对方是字符串,直接比较;
4、其他返回false
4. Если это число, другая сторона является объектом, и объект сравнивается с valueOf() или toString(), а все остальные возвращают false
Five, null, undefined не будут преобразованы, но они равны
Метод .toString() и преобразование значения метода .valueOf()
Обычно мы думаем, что преобразование объекта в строку требует вызова метода toString(), а преобразование объекта в число требует вызова метода valueOf(), но в реальном приложении это не так просто, см. следующий пример кода:
let obj = {
name: "draven",
age: 28
}
console.log(obj.toString()); //[object Object]
Точно так же давайте посмотрим на метод valueOf():
let arr = [1, 2, 3];
console.log(arr.valueOf());//[1, 2, 3]
Как видно из приведенного выше кода, метод valueOf() не преобразует объект в число, отражающее этот объект. Вместо этого мы используем toString()
let arr = [1, 2, 3];
console.log(arr.toString());//1,2,3
Примечание: многие друзья думают, что для преобразования в строку сначала должен быть вызван метод toString(). На самом деле это неправильное понимание. Мы должны понимать, что вызов метода toString() может преобразовать его в строку, но это не так. не обязательно первый вызов метода преобразования строки toString().
Давайте посмотрим на следующий код:
let arr = {};
arr.valueOf = function () { return 1; }
arr.toString = function () { return 2; }
console.log(arr == 1);//true
let arr = {};
arr.valueOf = function () { return []; }
arr.toString = function () { return 1; }
console.log(arr == 1);//true
Из приведенного выше кода видно, что преобразование сначала вызывает valueOf(), если valueOf() не является значением, то для преобразования будет вызываться toString!
let arr = {};
arr.valueOf = function () { return "1"; }
arr.toString = function () { return "2"; }
console.log(arr == "1");//true
Если "1" является строкой, она сначала вызовет valueOf().
let arr = [2];
console.log(arr + "1");//21
В приведенном выше примере вызывается toString(), потому что за arr.toString() следует 2.
Процесс конвертации такой: во-первых, arr вызовет сначала метод valueOf(), но этот метод чисел просто наследуется и не переписывается (разумеется, это переписывание не является нашей реализацией), возвращаемое значение — это сам объект массива , а не тип значения, поэтому вместо этого вызывается метод toString(), поэтому цель преобразования в строку достигается.
иллюстрировать
Большинство объектов неявно преобразуются в типы значений при первой попытке вызвать метод valueOf(). Но объект Date является исключением. Методы valueOf() и toString() этого объекта были тщательно переписаны. По умолчанию используется вызов метода toString(), например, с помощью оператора +. Если он есть в других арифметических операциях , вместо него будет вызван метод valueOf().
let date = new Date();
console.log(date + "1"); //Sun Apr 17 2014 17:54:48 GMT+0800 (CST)1
console.log(date + 1);//Sun Apr 17 2014 17:54:48 GMT+0800 (CST)1
console.log(date - 1);//1460886888556
console.log(date * 1);//1460886888557
пример укрепления Давайте вместе ответим на следующие вопросы!
let a;
console.dir(0 == false);//true
console.dir(1 == true);//true
console.dir(2 == {valueOf: function(){return 2}});//true
console.dir(a == NaN);//false
console.dir(NaN == NaN);//false
console.dir(8 == undefined);//false
console.dir(1 == undefined);//false
console.dir(2 == {toString: function(){return 2}});//true
console.dir(undefined == null);//true
console.dir(null == 1);//false
console.dir({ toString:function(){ return 1 } , valueOf:function(){ return [] }} == 1);//true
console.dir(1=="1");//true
console.dir(1==="1");//false
[] == 0 // true
Все вышесказанное понятно? По какой причине последняя строка кода возвращает true?
es6
В этой части проверяется владение es6, некоторыми новыми типами, синтаксисом и так далее. Рекомендую всем посмотретьСтатья Es6 учителя Руан Ифэн
рукописная реализация
js реализует привязку
// 实现bind
Function.prototype.myBind = function (context,...args) {
let self = this;
let params = args;
return function (...newArgs) {
self.call(context, ...params.concat(...newArgs))
}
}
var a = {
name: 'this is a'
}
function sayName() {
console.log(this.name, arguments)
}
let newfn = sayName.myBind(a, '1234', '5678')
newfn('1000', '2000')
js реализует вызов
// 实现call
Function.prototype.myCall = function (context,...args) {
context.fn = this;
context.fn(...args)
delete context.fn;
}
var a = {
name: 'this is a'
}
function sayName() {
console.log(this.name, arguments)
}
sayName.myCall(a, '1234', '5678')
js реализует setInterval
// setTimeout 实现setInterval
function mySetInterval(fn, time) {
let timer = {};
function timeout() {
timer.t = setTimeout(() => {
fn();
timeout()
}, time)
}
timeout();
return timer;
}
function clearMyInterval(timer) {
clearTimeout(timer.t)
}
promise
Есть много точек проверки обещаний, в том числе точки знаний для реализации ваших собственных обещаний и некоторых вызовов.
Рекомендуется две статьи:Реализовать обещанияа такжеОбещания
css
- Блочная модель, каковы характеристики полей и отступов блочной модели?
- Каковы свойства гибкого макета и что они означают?
- Каков метод реализации макета с центрированием слева-справа, макета с центрированием сверху-снизу, макета с центрированием сверху-снизу слева-справа?
- Одна строка превышает опущение..., многострочная превышает опущение...
- Адаптивная верстка
- Адаптивный макет
- меньше, scss, стилус
- рем, эм, vw и т. д.
- Как добиться 1px на мобильном телефоне?
- Как css реализует треугольники?
- В чем разница между ссылкой и импортом css?
html
- для чего используется мета
- Различия и примеры блочных и линейных элементов
- Какие новые теги в html5?
- Использование тегов видео, событий и т. д.
внешний фреймворк
vue
базовый
1. Жизненный цикл vue: перед созданием, созданием, перед монтированием, монтированием, перед обновлением, обновлением, перед удалением, уничтожением;
2. Связь компонента Vue:
- реквизит (излучать);
- $attr и $listeners,
- объект шины событий (bus.$on, bus.$emit),
- предоставлять (вводить),
- v-модель (реквизит: значение, излучение: ввод),
- $ дети,
- vuex
3. Использование и принцип работы алгоритма keep-alive, LRU
4. Разница между v-show и v-if для vue, разница между watch и вычислением для vue;
5. Другое: рендеринг Vue на стороне сервера, например, использование фреймворка nuxt, использование библиотек внешних компонентов, таких как element-ui;
vue2 и vue3
3 — Proxy+Reflect, 2 — Object.defineProperty, оптимизация dom-diff, componentApi и т. д.
vue-router
- Реализован режим: хеш и история, разница и анализ двух
- Событие: Глобальное: beforeEach, afterEach; Маршрутизация: beforeEnter; В компоненте: beforeRouteEnter, beforeRouteUpdate, beforeRouteLeave
- Принцип реализации, исходный код
vuex
- что такое векс?официальный сайт векс
- состояние, геттеры, мутации (фиксация), действия (отправка), модуль
- mapState, mapMutations, mapGetters, mapActions, подписка, subscribeAction
- Принцип реализации, исходный код и т.д.
react
1. Жизненный цикл
1.react16之前的生命周期是什么?
2.react16之后的生命周期是什么?
3.react16和react16之前的版本有什么区别?
4.requestAnimationFrame是什么?requestIdleCallback是什么?如何实现requestAnimationFrame
// 实现requestAnimationFrame
var lastTime = 0
window.requestAnimationFrame = function (callback) {
let now = Date().now;
let timeCall = Math.max(0, 16 - (lastTime - now));
let id = setTimeout(function () {
callback(now + timeCall)
}, timeCall)
lastTime = now + timeCall;
return id;
}
2. реагирующие крючки
1.常用的reacthooks都有哪些?
2.使用useEffect模拟componentDidMount和componentDidUpdate
3.useEffect返回的是什么?做什么用的?
4.useEffect和useLayoutEffect的区别是什么?
5、useMemo和useCallback是什么?做什么用的?有什么区别?
3. реактивный маршрутизатор
1.如何实现路由切换,有几种方式?
2.有哪几个钩子函数?onEnter和routerWillLeave
3.link与a标签的区别什么?
В-четвертых, редукс
1.redux是什么?做什么的?与vuex有什么区别?
2.redux包含哪几块?state,reducers,actions
5. Другие:
1.服务端渲染next;
2.组件库antd;
3.PureComponent与Component的区别是什么?
4.react的性能优化有什么建议?
5.封装一个promise的setState
// 使用promise封装setState
function setStateP(state) {
return new Promise(resolve => {
this.setState(state, resolve)
})
}
Тип инструмента - веб-пакет
- 1. Что такое веб-пакет?
- 2. Каков принцип работы Webpack?
- 3. Вы написали плагин? Как?
- 4. Что делает загрузчик? В чем разница между загрузчиком и плагином?
- 5. Предложения по оптимизации для веб-пакета и т. д.
nodeJs
- цикл событий: вы можете прочитать эту статьюцикл событий nodejs
- яйцо: цикл объявления, структура каталогов, общие плагины
- koa: разница между промежуточным программным обеспечением Koa и промежуточным программным обеспечением Express, функция, которая реализует модель лукового кольца.
// 洋葱圈模型 function compose(middleware) { return function (context, next) { let index = -1; function dispatch(i) { if (i <= index) { return Promise.reject('err') } index = i; let fn = middleware[i]; if(i === middleware.length) { fn = next; } if (!fn) { return Promise.resolve(); } try { return Promise.resolve(fn(context, function next() { return dispatch(i + 1); })) } catch (e) { return Promise.reject(e); } } dispatch(0); } }
child_process
-
- спавн, exec, execFile, форк,
-
- Fork похож на spawn, разница в том, что fork должен выполнять файлы js для создания дочерних процессов;
-
- Разница между spawn и exec и execFile заключается в том, что атрибут тайм-аута может быть указан для установки времени тайм-аута при создании последних двух, и когда процесс истечет, он будет уничтожен;
-
- Разница между exec и execFile заключается в том, что exec выполняет существующую команду, а execFile выполняет файл.
pm2
- общие команды pm2: запуск, остановка, удаление, журналы, перезапуск, список
- -i параметр, запускать многопоточность, смотреть, -w, следить за изменениями в файле
- файл конфигурации pm2, вы можете настроить несколько приложений, массив приложений, запустить pm2 start pm2.config.js --only=one-app-name
Основы компьютера
http серия
- Что такое трехстороннее рукопожатие? Зачем тебе три раза?
- Что такое четыре волны? Зачем тебе четыре раза?
- В чем разница между http1, http2, https?
- Как HTTPS зашифрован?
- Как отменить запрос? ПрерватьКонтроллер
Сортировать
- Пузырьковая сортировка
// 从小到大排序:
function bubblingSort(list){
let temp;
for(let i=0; i<list.length; i++){
for(let j=i; j<list.length; j++){
if(list[i] > list[j]){
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
return list;
}
let res = bubblingSort([10, 8, 2, 23, 30, 4, 7, 1])
console.log(res); // [1, 2, 4, 7, 8, 10, 23, 30]
- сортировка прямым выбором
从小到大排序:
function selectSort(list){
let r,temp;
for(let j=0; j<list.length; j++){
for(let i = j+1; i<list.length; i++){
if(list[j] > list[i]){
temp = list[j];
list[j] = list[i];
list[i] = temp;
}
}
}
return list;
}
let res = selectSort([10, 8, 2, 23, 30, 4, 7, 1])
console.log(res); // [1, 2, 4, 7, 8, 10, 23, 30]
- сортировка прямой вставкой
Весь процесс сортировки состоит из n-1 вставок, то есть первая запись в последовательности рассматривается как упорядоченная подпоследовательность, а затем одна за другой вставляется вторая запись, пока вся последовательность не будет упорядочена.
function insertSort(list) {
let flag;
for(let index = 1; index < list.length; index++) {
flag = list[index];
let j = index - 1;
while (flag < list[j]) {
list[j + 1] = list[j]
j--;
}
list[j + 1] = flag;
}
return list;
}
let res = insertSort([10, 8, 2, 23, 30, 4, 7, 1])
console.log(res); // [1, 2, 4, 7, 8, 10, 23, 30]
- Сортировка холмов
Процесс сортировки: сначала взять натуральное число d1 В результате одной сортировки сортируемые записи делятся на две независимые части, причем ключевые слова одной части записей меньше ключевых слов другой части записей. Ответа нет, я просто сортирую и обобщаю соответствующий контент, который я разобрал.Если ответа нет, я все равно должен проверить это сам. Кодировать слова непросто, двигайте пальцем, чтобы поставить лайк, а затем идите~~~ Наконец, я желаю вам всем удачи, если вы смените работу, вы можете найти работу, которая вам нравится.function shellSort(list) {
const length = list.length;
let j, temp;
for (let d = parseInt(length / 2); d >= 1; d = parseInt(d / 2)) {
for (let i = d; i < length; i++) {
temp = list[i];
j = i - d;
while (j >= 0 && temp < list[j]) {
list[j + d] = list[j];
j -= d;
}
list[j + d] = temp;
}
}
return list;
}
let res = shellSort([10, 8, 2, 23, 30, 4, 7, 1])
console.log(res); // [1, 2, 4, 7, 8, 10, 23, 30]
function quickSort(v,left,right){
if(left < right){
var key = v[left];
var low = left;
var high = right;
while(low < high){
while(low < high && v[high] > key){
high--;
}
v[low] = v[high];
while(low < high && v[low] < key){
low++;
}
v[high] = v[low];
}
v[low] = key;
quickSort(v,left,low-1);
quickSort(v,low+1,right);
}
}
let list = [10, 8, 2, 23, 30, 4, 7, 1]
quickSort(list, 0, 7)
console.log(list); // [1, 2, 4, 7, 8, 10, 23, 30]
разное
разное
1、什么是hybrid?
2、jsbridge是什么?如何实现?
3、hybrid开发需要注意什么?
1.包括图片视频等内容的懒加载(IntersectionObserver的使用封装)
2.数据的预加载,纯h5的prefetch && 与端结合的预加载方案
3.js的按需加载(配合webpack的import().then()的split实现)
1、 解析HTML结构。
2、 加载外部脚本和样式表文件。
3、 解析并执行脚本代码。
4、 构造HTML DOM模型。//ready
5、 加载图片等外部文件。
6、 页面加载完毕。//load
此问题网上有很多回答,属于自由发挥问题;回答的深度和广度能够看出本人的知识面。此处就不多说了。
Суммировать