предисловие
刚入职半个月,无缝对接的加入了新公司,完美。抽空整理了下最近遇到的面试题,面试公司包括:阿里,腾讯,美的,顺丰,平安金服。base是深圳,后三个都比较顺利拿到了offer,离大厂还有点差距,加油鸭~
因为是初级前端,面试题可能过于基础,有错误望指出😄。
有些问题当场没有很全面的答出,后续上网查资料补齐了,可能会有很多雷同,哈哈
有很多题目在这个网站能看到,强推一波:https://muyiy.cn/question/
1. Представьте BFC и его применение
- BFC 即 Block Formatting Contexts (块级格式化上下文),是页面盒模型布局中的一种 CSS 渲染模式,相当于一个独立的容器,里面的元素和外部的元素相互不影响。
- 创建 BFC 的方式有:
html 根元素
float 浮动
position (absolute、fixed)
overflow 除了 visible 以外的值 (hidden、auto、scroll)
display 为 inline-block、table-cells、flex
Особенности BFC
1) Маржа рухнет под тем же BFC.
В следующем примере расстояние между двумя прямоугольниками составляет всего 100 пикселей. Это не ошибка CSS. Мы можем понимать это как спецификацию. Если вы хотите избежать перекрывающихся полей, вы можете поместить их в разные контейнеры BFC.
<head>
<style>
div{
width: 100px;
height: 100px;
margin: 100px;
border: 1px solid red;
}
</style>
</head>
<body>
<div></div>
<div></div>
</body>
можно изменить на это
<head>
<style>
p{
width: 100px;
height: 100px;
margin: 100px;
border: 1px solid red;
}
div{
overflow: hidden;
}
</style>
</head>
<body>
<div>
<p></p>
</div>
<div>
<p></p>
</div>
</body>
2) BFC может содержать плавающие элементы (очистить плавающие элементы)
<head>
<style>
p{
width: 100px;
height: 100px;
background: black;
float: left;
}
div{
width: 100%;
border: 1px solid red;
/* 清除浮动 div可包含浮动的元素*/
overflow: hidden;
}
</style>
</head>
<body>
<div>
<p></p>
</div>
</body>
3) BFC может предотвратить закрытие элементов плавающими элементами.
Ниже приведен эффект обтекания текстом.
<head>
<style>
div{
width: 100px;
height: 100px;
background: #4CAF50;
float: left;
}
section{
width: 300px;
border: 1px solid red;
margin: 100px;
}
</style>
</head>
<body>
<section>
<div>我在左边浮动</div>
<p>这是一段文字,BFC 即 Block Formatting Contexts (块级格式化上下文),是页面盒模型布局中的一种 CSS 渲染模式,相当于一个独立的容器,里面的元素和外部的元素相互不影响。</p>
</section>
</body>
Добавить overflow: hidden к элементу p
p{
overflow: hidden;
}
Этот метод можно использовать для реализации двухколоночного адаптивного макета с фиксированной шириной слева и адаптивной шириной справа.
2. Методы оценки массивов, укажите различия, преимущества и недостатки между ними соответственно.
Object.prototype.toString.call()、instanceof、Array.isArray()以及typeof
1) Object.prototype.toString.call()
Каждый объект, который наследует Object, имеет метод toString.Если метод toString не переопределен, он вернет [тип объекта], где тип — это тип объекта. Но когда метод toString используется непосредственно для других типов, кроме Object типа, он будет напрямую возвращать строку с содержимым, поэтому нам нужно использовать метод call или apply для изменения контекста выполнения метода toString.
const an = ['Hello','World'];
an.toString(); // "Hello,World"
Object.prototype.toString.call(an); // "[object Array]"
Этот метод работает для всех основных типов данных, даже для null и undefined. Однако пользовательский тип объекта нельзя отличить, а пользовательский тип можно отличить по instanceof.
console.log(Object.prototype.toString.call("this"));//[object String]
console.log(Object.prototype.toString.call(12));//[object Number]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call({name: "this"}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call([]));//[object Array]
console.log(Object.prototype.toString.call(new Date));//[object Date]
console.log(Object.prototype.toString.call(/\d/));//[object RegExp]
function Person(){};
console.log(Object.prototype.toString.call(new Person));//[object Object]
Object.prototype.toString.call() часто используется для определения встроенных объектов браузера.
2) пример
Внутренний механизм instanceof заключается в том, чтобы определить, можно ли найти прототип типа в цепочке прототипов объекта.
Используйте instanceof, чтобы определить, является ли объект массивом, instanceof оценит, можно ли найти прототип соответствующего массива в цепочке прототипов объекта, и вернет true, если он найден, иначе он вернет false.
Но instanceof можно использовать только для определения типа объекта, а не примитивных типов. И все типы объектов instanceof Object имеют значение true.
instanceof Array; // true
instanceof Object; // true
'a' instanceof String; //false
3) Массив.isArray()
- Функция: используется для определения того, является ли объект массивом.
- instanceof и isArray
Array.isArray предпочтительнее instanceof при обнаружении экземпляров Array, поскольку Array.isArray может обнаруживать iframe.
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]
// Correctly checking for Array
Array.isArray(arr); // true
Object.prototype.toString.call(arr); // true
// Considered harmful, because doesn't work though iframes
arr instanceof Array; // false
- Array.isArray() и Object.prototype.toString.call()
Array.isArray() — это новый метод в ES5.Если Array.isArray() не существует, его можно реализовать с помощью Object.prototype.toString.call().
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
4) тип
typeof 只能检测基本数据类型,包括boolean、undefined、string、number、symbol,而null、Array、Object ,使用typeof检测出来都是Object,无法检测具体是哪种引用类型。
3. Как центрировать div по горизонтали и вертикали
<div class="parent">
<div class="child"></div>
</div>
1) Используйте position + transform, когда ширина и высота не фиксированы
.parent{
position: relative;
}
.child{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
2) Используйте позицию + преобразование, когда есть ширина и высота
.parent{
position: relative;
}
.child{
width: 100px;
height: 100px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -50px;
margin-top: -50px;
}
3) Используйте гибкость
.parent{
display: flex;
align-items: center;
justify-content: center;
}
или
.parent{
display: flex;
align-items: center;
}
.child{
margin: 0 auto;
}
или
.parent{
display: flex;
}
.child{
margin: auto;
}
4) Использовать позицию
.parent{
position: relative;
}
.child{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
5) Используйте сетку
.parent{
display: grid;
}
.child{
justify-self: center;
align-self: center;
}
6) Используйте таблицу
.parent{
display: table;
}
.child{
display: table-cell;
vertical-align: middle;
text-align: center;
}
или
.parent {
display: table-cell;
text-align: center;
vertical-align: middle;
}
.child {
display: inline-block;
}
7) Используйте псевдоклассы
.parent{
font-size: 0;
text-align: center;
}
.parent::before {
content: "";
display: inline-block;
width: 0;
height: 100%;
vertical-align: middle;
}
.child{
display: inline-block;
vertical-align: middle;
}
4. Что печатает следующий код и почему?
var b = 10;
(function b(){
b = 20;
console.log(b);
})();
В обычном режиме:
var b = 10;
(function b() {
// 内部作用域,会先去查找是有已有变量b的声明,有就直接赋值20,确实有了呀。发现了具名函数 function b(){},拿此b做赋值;
// IIFE的函数无法进行赋值(内部机制,类似const定义的常量),所以无效。
// (这里说的“内部机制”,想搞清楚,需要去查阅一些资料,弄明白IIFE在JS引擎的工作方式,堆栈存储IIFE的方式等)
b = 20;
console.log(b); // [Function b]
console.log(window.b); // 10,不是20
})();
В строгом режиме будет сообщено об ошибке:
var b = 10;
(function b() {
'use strict'
b = 20;
console.log(b)
})() // "Uncaught TypeError: Assignment to constant variable."
Есть окна:
var b = 10;
(function b() {
window.b = 20;
console.log(b); // [Function b]
console.log(window.b); // 20是必然的
})();
Есть вары:
var b = 10;
(function b() {
var b = 20; // IIFE内部变量
console.log(b); // 20
console.log(window.b); // 10
})();
5. Что печатает следующий код и почему?
var a = 10;
(function () {
console.log(a)
a = 5
console.log(window.a)
var a = 20;
console.log(a)
})()
Результат первый
По порядку: не определено, 10, 20
var a = 10;
(function () {
//函数里面重新定义了a,变量提升,预解析
console.log(a);//undefined
a = 5;
console.log(window.a);//10,a是函数局部变量
var a = 20;
console.log(a);//当然20
})()
console.log(a);//10,相当于window.a
Замените его на это:
var a = 10;
(function () {
//函数里面没有重新定义
console.log(a);//10
a = 5;
console.log(window.a);//5
a = 20;
console.log(a);//当然20
})()
console.log(a);//20,相当于window.a
Замените его на это:
var a = 10;
function b() {
//函数里面重新定义了a,变量提升,预解析
console.log(a);//undefined
a = 5;
console.log(window.a);//10,a是函数局部变量
var a = 20;
console.log(a);//当然20
}
b();
console.log(a);//10,相当于window.a
6. Краткое введение в Repaint & Reflow и способы оптимизации
Давайте сначала посмотрим на процесс рендеринга браузера
На картинке выше мы видим, что процесс рендеринга в браузере выглядит следующим образом:
1、解析HTML,生成DOM树,解析CSS,生成CSSOM树
2、将DOM树和CSSOM树结合,生成渲染树(Render Tree)
3、Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)
4、Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
5、Display:将像素发送给GPU,展示在页面上。(这一步其实还有很多内容,比如会在GPU将多个合成层合并为同一个层,并展示在页面中,而css3硬件加速的原理则是新建合成层)
Процесс рендеринга выглядит достаточно просто, давайте подробнее рассмотрим, что именно делает каждый шаг.
Генерация дерева рендеринга
Чтобы построить дерево рендеринга, браузер в основном выполняет следующую работу:
- Пройдите каждый видимый узел, начиная с корня дерева DOM.
- Для каждого видимого узла найдите соответствующие правила в дереве CSSOM и примените их.
- На основе каждого видимого узла и соответствующего ему стиля в комбинации создается дерево рендеринга.
На первом этапе, поскольку мы говорили об обходе видимых узлов, мы должны сначала узнать, какие узлы невидимы. К невидимым узлам относятся:
- Некоторые узлы, которые не будут отображать выходные данные, такие как скрипт, мета, ссылка и т. д.
- Некоторые узлы скрыты через css. Например, отображение: нет. Обратите внимание, что узлы, скрытые видимостью и непрозрачностью, все равно будут отображаться в дереве рендеринга. Только узлы с display:none не будут отображаться в дереве рендеринга.
Примечание. Дерево рендеринга содержит только видимые узлы.
переплавка
Ранее при построении дерева рендеринга мы комбинировали видимые DOM-узлы и соответствующие им стили, но нам также нужно было рассчитать их точное положение и размер в пределах области просмотра устройства.Этап этого расчета — reflow.
Чтобы определить точный размер и положение каждого объекта на веб-сайте, браузер переходит от корня дерева рендеринга, что мы можем представить в следующем примере:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Critial Path: Hello world!</title>
</head>
<body>
<div style="width: 50%">
<div style="width: 50%">Hello world!</div>
</div>
</body>
</html>
Мы видим, что первый div устанавливает размер отображения узла равным 50% ширины окна просмотра, а второй div устанавливает его размер равным 50% родительского узла. На этапе перекомпоновки нам нужно преобразовать его в фактическое значение пикселя в соответствии с конкретной шириной области просмотра.
перерисовать
Наконец, построив дерево рендеринга и стадию перекомпоновки, мы знаем, какие узлы видимы, а также стиль видимых узлов и конкретную геометрическую информацию (положение, размер), после чего мы можем преобразовать каждый узел дерева рендеринга в фактический. пикселей на экране, этот этап называется узлом перерисовки.
Теперь, когда мы знаем процесс рендеринга в браузере, давайте обсудим, когда происходит перерисовка перерисовки.
Когда происходит перерисовка оплавления
Как мы знаем ранее, этот этап перекомпоновки в основном предназначен для расчета положения и геометрической информации узлов, поэтому при изменении макета страницы и геометрической информации требуется перекомпоновка. Например следующая ситуация:
- Добавить или удалить видимые элементы DOM
- Положение элемента меняется
- Изменяются размеры элемента (включая поля, внутренние границы, размер границы, высоту и ширину и т. д.)
- Изменения содержимого, такие как изменение текста или замена изображения другим изображением другого размера.
- При первом отображении страницы (это определенно неизбежно)
- Изменяется размер окна браузера (поскольку перекомпоновка вычисляет положение и размер элементов на основе размера окна просмотра)
Примечание. Перекомпоновка всегда вызывает перерисовку, а перерисовка не обязательно приводит к перерисовке.
В зависимости от объема и масштаба изменений необходимо пересчитать большие или меньшие части дерева рендеринга, а некоторые изменения вызовут перекомпоновку всей страницы, например, когда появляется полоса прокрутки или изменяется корневой узел.
Механизм оптимизации браузера
Современные браузеры достаточно умны, чтобы оптимизировать процесс перерисовки, ставя изменения в очередь и выполняя их пакетами, поскольку каждая перерисовка требует дополнительных вычислительных затрат. Браузер поместит операцию модификации в очередь, и очередь не будет очищена до тех пор, пока не пройдет определенный период времени или пока операция не достигнет порогового значения. но! Очередь принудительно обновляется, когда вы получаете информацию о макете, например, когда вы получаете доступ к следующим свойствам или используете следующие методы:
- offsetTop, offsetLeft, offsetWidth, offsetHeight
- scrollTop, scrollLeft, scrollWidth, scrollHeight
- clientTop, clientLeft, clientWidth, clientHeight
- getComputedStyle()
- getBoundingClientRect
- В частности, вы можете посетить этот веб-сайт:gist.GitHub.com/Пол Айриш/5…
Все вышеперечисленные свойства и методы должны возвращать последнюю информацию о макете, поэтому браузер должен очистить очередь и инициировать перерисовку перерисовки, чтобы вернуть правильное значение. Поэтому, когда мы изменяем стиль, лучше не использовать перечисленные выше свойства, они будут обновлять очередь рендеринга. Если вы собираетесь их использовать, лучше кэшировать значения.
Уменьшите количество перекомпоновок и перерисовок
Что ж, к нашему главному сегодняшнему событию, с таким большим количеством предыстории и теоретических знаний, давайте поговорим о том, как уменьшить перекомпоновку и перерисовку.
Минимизируйте перерисовки и перекомпоновки
Поскольку перерисовка и перекомпоновка могут быть дорогостоящими, лучше уменьшить количество таких операций. Чтобы уменьшить количество вхождений, мы можем объединить несколько изменений в DOM и стилях, а затем обработать их все сразу. Рассмотрим этот пример
const el = document.getElementById('test');
el.style.padding = '5px';
el.style.borderLeft = '1px';
el.style.borderRight = '2px';
В примере изменены три свойства стиля, каждое из которых влияет на геометрию элемента, вызывая перекомпоновку. Конечно, большинство современных браузеров оптимизируют его так, что срабатывает только одна перекомпоновка. Однако, если другой код получает доступ к информации о макете (информация о макете, которая запускает перекомпоновку выше) в более старом браузере или при выполнении вышеуказанного кода, это вызовет три перекомпоновки.
Поэтому мы можем объединить все изменения и обрабатывать их последовательно, например, мы можем сделать следующее:
- использовать cssтекст
const el = document.getElementById('test'); el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';
- Изменить класс CSS
const el = document.getElementById('test'); el.className += ' active';
Конкретная ссылка:Как дерево Способность /вопрос/например…
7. Выровняйте текст по обоим концам
<div>姓名</div>
<div>手机号码</div>
<div>账号</div>
<div>密码</div>
div {
margin: 10px 0;
width: 100px;
border: 1px solid red;
text-align: justify;
text-align-last: justify;
}
8. Каков результат ['1', '2', '3'].map(parseInt)?
先说结果:
['1', NaN, NaN]
为什么不是['1', '2', '3']呢,下面开始分析
-
Метод map() возвращает новый массив, элементами которого являются значения, обработанные вызывающей функцией элементов исходного массива.
-
Метод map() последовательно обрабатывает элементы в исходном порядке элементов массива.
map(parseInt) на самом деле:
map(function(item, index){
return parseInt(item, index);
})
То есть запускать последовательно:
parseInt('1', 0);
parseInt('2', 1);
parseInt('3', 2);
Использование parseInt
- Функция parseInt(string, radix) анализирует строку и возвращает целое число.
- Когда значение параметра счисления равно 0 или параметр не установлен, parseInt() будет оценивать основание числа в соответствии со строкой.
- основание необязательно. Указывает основание числа для анализа. Значение находится в диапазоне от 2 до 36.
так: parseInt('1', 0);//'1' parseInt('2', 1);//NaN parseInt('3', 2);//NaN, потому что в двоичном коде нет 3
9. Напишите результат печати следующего кода
function changeObjProperty(o) {
o.siteUrl = "http://www.baidu.com";
o = new Object();
o.siteUrl = "http://www.google.com";
}
let webSite = new Object();
changeObjProperty(webSite);
console.log(webSite.siteUrl);
На первый взгляд, этот вопрос представляет собой небольшую проблему, но на самом деле это скрытая загадка. Сначала ответьте:
console.log(webSite.siteUrl);//"http://www.baidu.com"
Повтор выглядит следующим образом:
function changeObjProperty(o) {
//o是形参,对象的引用,依旧指向原地址,相当于 var o = webSite;赋值改变对象的属性
o.siteUrl = "http://www.baidu.com";
//变量o指向新的地址 以后的变动和旧地址无关,题目打印的是外部webSite.siteUrl
o = new Object();
o.siteUrl = "http://www.google.com";
}
Измените заголовок на следующий:
function changeObjProperty(o) {
o.siteUrl = "http://www.baidu.com";
o = new Object();
o.siteUrl = "http://www.google.com";
return o;
}
let webSite = new Object();
changeObjProperty(webSite);
console.log(webSite.siteUrl);
let newSite = changeObjProperty(webSite);
console.log(newSite.siteUrl);
На данный момент результат печати выглядит следующим образом:
console.log(webSite.siteUrl);//"http://www.baidu.com"
console.log(newSite.siteUrl);//"http://www.google.com"
10. Дедупликация массива
var arr = [2,0,1,9,1,0,2,1];
- indexOf
var arr = [2,0,1,9,1,0,2,1];
var a_arr = [];
for(let i=0;i<arr.length;i++){
if(a_arr.indexOf(arr[i]) == -1){
a_arr.push(arr[i]);
}
}
console.log(a_arr);
- два для петель
var arr = [2,0,1,9,1,0,2,1,4];
var a_arr = [];
for(let i=0;i<arr.length;i++){
var flag = true;
for(let j=0;j<a_arr.length;j++){
if(arr[i] == arr[j]){
flag = false;
}
}
if(flag){
a_arr.push(arr[i]);
}
}
console.log(a_arr);
- Метод установки ES6
var arr = [2,0,1,9,1,0,2,1,4];
var a_arr = [...new Set(arr)]
console.log(a_arr);
- метод фильтрации
var arr = [2,0,1,9,1,0,2,1,4];
function unique(array) {
var res = array.filter(function(item, index, array){
return array.indexOf(item) === index;
})
return res;
}
console.log(unique(arr));
11. Что происходило в процессе страницы от ввода URL до загрузки и отображения страницы?
1、浏览器会开启一个线程来处理这个请求,对 URL 分析判断如果是 http 协议就按照 Web 方式来处理;
2、调用浏览器内核中的对应方法,比如 WebView 中的 loadUrl 方法;
3、通过DNS解析获取网址的IP地址,设置 UA 等信息发出第二个GET请求;
4、进行HTTP协议会话,客户端发送报头(请求报头);
5、进入到web服务器上的 Web Server,如 Apache、Tomcat、Node.JS 等服务器;
6、进入部署好的后端应用,如 PHP、Java、JavaScript、Python 等,找到对应的请求处理;
7、处理结束回馈报头,此处如果浏览器访问过,缓存上有对应资源,会与服务器最后修改时间对比,一致则返回304;
8、浏览器开始下载html文档(响应报头,状态码200),同时使用缓存;
9、文档树建立,根据标记请求所需指定MIME类型的文件(比如css、js),同时设置了cookie;
10、页面开始渲染DOM,JS根据DOM API操作DOM,执行事件绑定等,页面显示完成。
12. Принципы и методы реализации ajax
AJAX不是JavaScript的规范,它来自一个缩写:Asynchronous JavaScript and XML,意思就是用JavaScript执行异步网络请求。
Собственные шаги запроса ajax
//创建 XMLHttpRequest 对象
var ajax = new XMLHttpRequest();
//规定请求的类型、URL 以及是否异步处理请求。
ajax.open('GET',url,true);
//发送信息至服务器时内容编码类型
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//发送请求
ajax.send(null);
//接受服务器响应数据
ajax.onreadystatechange = function () {
if (obj.readyState == 4 && (obj.status == 200 || obj.status == 304)) {
}
};
13. Рассказать о принципе key in vue
便于diff算法的更新,key的唯一性,能让算法更快的找到需要更新的dom,需要注意的是,key要唯一,不然会出现很隐蔽性的更新问题。
14. Каков принцип двусторонней привязки Vue?
双向数据绑定是基于Object.defineProperty()重新定义get和set方法实现的。修改触发set方法赋值,获取触发get方法取值,并通过数据劫持发布信息。
let obj = {
name: 't-one',
location: {x: 100, y: 200}
}
function render(){
console.log('渲染视图');
}
function observe(data){
for(let key in data){
defineData(data, key, data[key]);
}
}
function defineData(data, key, value){
Object.defineProperty(data, key, {
get(){
return value;
},
set(newValue){
render();
value = newValue;
}
})
}
observe(obj);
obj.name = 'liu';
console.log(obj.name);//liu
Простая двусторонняя привязка
<input type="text" id="input">
<div id="content"></div>
<script>
function obersver(data){
for(let i in data){
defineData(data,i,data[i]);
}
}
function defineData(data,key,value){
Object.defineProperty(data,key,{
get:function(){
return value;
},
set: function(newValue){
console.log('调用了set====');
value = newValue;
document.getElementById('content').innerHTML = newValue;
}
})
}
let obj = {};
document.addEventListener('keyup',function(e){
obersver(obj);
obj.text = e.target.value;
console.log(obj.text);
})
</script>
15. Какова функция $nextTick в vue?
处理数据动态变化后,dom还未及时更新的问题。$nextTick就可以获取到数据更新后最新的dom变化
16. Говоря о фронтенд-инжиниринге, модульности и компонентизации
Фронтенд-инжиниринг
1、将前端项目当成一项系统工程进行分析、组织和构建从而达到项目结构清晰、分工明确、团队配合默契、开发效率提高的目的
2、工程化思维就是“结构、样式和动作分离”。如目录分为assets,components,router,util
Передняя часть модульная
1、可以简单的认为模块化和组件化是工程化的表现形式
2、JS模块化方案很多有AMD/CommonJS/UMD/ES6 Module等,CSS模块化开发大多是在less、sass、stylus
es6 привносит модульный подход, встроенный в язык:
const methodOne = params => {
console.log(params)
}
const methodTwo = params => {
console.log(params)
}
// 导出方式 1
export default {
methodOne,
methodTwo
}
// 导出方式 2
export {
methodOne,
methodTwo
}
// 引入方式 1 对应导出方式 1
import module from './module'
module.methodOne();
// 引入方式2 对应导出方式 2
import { methodOne } from './module'
methodOne();
Компонентизация интерфейса
1、组件化将页面视为一个容器,页面上各个独立部分例如:头部、导航、焦点图、侧边栏、底部等视为独立组件,不同的页面根据内容的需要,去盛放相关组件即可组成完整的页面。
2、模块化和组件化一个最直接的好处就是复用
17. Разница между ссылкой и @import в css
1、@import是 CSS 提供的语法规则,只有导入样式表的作用;link是HTML提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等。
2、加载页面时,link引入的CSS被同时加载,@import引入的CSS将在页面加载完毕后加载。
3、link标签作为HTML元素,不存在兼容性问题,而@import是CSS2.1才有的语法,故老版本浏览器(IE5之前)不能识别。
4、可以通过JS操作DOM,来插入link标签改变样式;由于DOM方法是基于文档的,无法使用@import方式插入样式。
18. Пожалуйста, напишите обычные 15-20 заглавных букв или цифр.
var reg = /[^A-Z\d]{15,20}/;
19. Что выводит следующий код
var fullName = 'a';
var obj = {
fullName: 'b',
prop:{
fullName: 'c',
getFullName: function(){
console.log(this);
return this.fullName
}
}
}
console.log(obj.prop.getFullName());
var test = obj.prop.getFullName;
console.log(test());
Объяснение следующее:
obj.prop.getFullName()这里this指向obj.prop,故
console.log(obj.prop.getFullName());//'c'
test = obj.prop.getFullName;此处this指向window,故
console.log(test());//'a'
20. Что выводит следующий код
var num = 1;
var myObject = {
num: 2,
add: function() {
this.num = 3;
(function() {
console.log(this.num);
this.num = 4;
})();
console.log(this.num);
},
sub: function() {
console.log(this.num)
}
}
myObject.add();
console.log(myObject.num);
console.log(num);
var sub = myObject.sub;
sub();
Объяснение следующее:
var num = 1;
var myObject = {
num: 2,
add: function() {
this.num = 3;
(function() {
//此时this指向window,故值为1
console.log(this.num);
//此时window.num = 4
this.num = 4;
})();
//此处this为myObject,故this.num=3
console.log(this.num);
},
sub: function() {
console.log(this.num)
}
}
myObject.add();//1,3
console.log(myObject.num);//3
console.log(num);//4
//此处this指向window
var sub = myObject.sub;
sub();//4
21. Что выводит следующий код
setTimeout(function(){
console.log(1)
}, 0)
new Promise(function executor(resolve){
console.log(2);
for(var i=0;i<100;i++){
i==99 && resolve();
}
console.log(3);
}).then(function(){
console.log(4);
});
console.log(5);
Объяснение следующее:
setTimeout 和 setInterval的运行机制是将指定的代码移出本次执行,等到下一轮 Event Loop 时,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就等到再下一轮 Event Loop时重新判断。
这意味着,setTimeout指定的代码,必须等到本次执行的所有同步代码都执行完,才会执行。
故最后输出1
new Promise是立即执行,先打印2,3,然后5,再执行then打印4,最后是1
故结果为:
2,3,5,4,1
22. Каковы средства оптимизации проекта vue?
前端方面:
1、路由懒加载
2、图片,资源放cdn
3、页面图片较多进行懒加载
4、骨架屏方案
5、采用服务端渲染---nuxt.js
服务器端:
开启gzip
23. Что такое мвк, мвп, мввм
mvc
模型(Model):数据保存
视图(View):用户界面。
控制器(Controller):业务逻辑
View 传送指令到 Controller
Controller 完成业务逻辑后,要求 Model 改变状态
Model 将新的数据发送到 View,用户得到反馈
mvp
1. 各部分之间的通信,都是双向的。
2. View 与 Model 不发生联系,都通过 Presenter 传递。
3. View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。
mvvm
View的变动,自动反映在 ViewModel,反之亦然。
24, vue, jq, react, угловая разница, их преимущества
jq
1、需要频繁操作dom
2、容易引起重绘和回流,影响页面性能
vue
1、mvvm模式,采用虚拟dom不需要频繁操作dom,通过双向绑定,用数据驱动页面变化,页面变化对应数据也发生变化,只需要关注数据层的业务逻辑,而无需关注视图层的更新。可以尽量减少无用的更新操作,提高dom渲染效率。
2、组件化开发,页面由若干个组建组成,可复用性高。
3、社区环境好,各类资源文档十分齐全。
4、通过Object.defineProperty() 方法,监控对数据的操作,从而可以自动触发数据同步。
react
1、虚拟dom。
2、一切都是组件,组件实例之间可以嵌套。
3、使用独特的jsx语法。
angular
1、AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观。
2、在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢。
25. Что такое виртуальный дом, в чем его преимущества и где он хранится?
Virtual DOM 可以理解为一个简单的JS对象,并且最少包含标签名( tag)、属性(attrs)和子元素对象( children)三个属性。
Преимущество:
1、具备跨平台的优势-由于 Virtual DOM 是以 JavaScript 对象为基础而不依赖真实平台环境,所以使它具有了跨平台的能力,比如说浏览器平台、Weex、Node 等。
2、提升渲染性能-Virtual DOM的优势不在于单次的操作,而是在大量、频繁的数据更新下,能够对视图进行合理、高效的更新。
为了实现高效的DOM操作,一套高效的虚拟DOM diff算法显得很有必要。通过找出本次DOM需要更新的节点来更新,其他的不更新。
3、是一个js对象,存储在内存中。
26. Расскажите о понимании webpack
1、Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。
2、Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
3、Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
4、Loader:模块转换器,用于把模块原内容按照需求转换成新内容。
5、Plugin:扩展插件,在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情。
6、Output:打包后文件输出的位置。
27. Расскажите о цикле событий
Нажмите здесь, чтобы узнать подробности 👇nuggets.capable/post/684490…
28. Представьте процесс рукопожатия HTTPS
1、客户端使用https的url访问web服务器,要求与服务器建立ssl连接
2、web服务器收到客户端请求后, 会将网站的证书(包含公钥)传送一份给客户端
3、客户端收到网站证书后会检查证书的颁发机构以及过期时间, 如果没有问题就随机产生一个秘钥
4、客户端利用公钥将会话秘钥加密, 并传送给服务端, 服务端利用自己的私钥解密出会话秘钥
5、之后服务器与客户端使用秘钥加密传输
Источник ссылки:Как дерево.Можно /вопрос/…
29. Как предотвратить CSRF-атаки и XSS-атаки
Предотвращение XSS-атак
1、HttpOnly 防止劫取 Cookie
2、输入检查-不要相信用户的所有输入
3、输出检查-存的时候转义或者编码
Предотвращение CSRF-атак
1、验证码
2、Referer Check
3、添加token验证
Источник ссылки:nuggets.capable/post/684490…
30. Используйте sort() для сортировки массива [3, 15, 8, 29, 102, 22] и вывода результата.
var arr = [3,15,8,29,102,22]
А. Используйте метод sort() напрямую.Метод сортировки по умолчанию преобразует элементы массива в строки, а затем сравнивает порядок символов в кодировке UTF-16 в строке для сортировки.
var brr = arr.sort();
console.log(brr);//[102,15,22,29,3,8]
б, сортировка, может получить функцию, возвращаемое значение — это значение сравнения относительного порядка двух чисел
var brr = arr.sort((a,b)=>a-b);
console.log(brr);//[3, 8, 15, 22, 29, 102]
- Возвращаемое значение больше 0, т.е. a-b > 0, a и b меняются местами.
- Возвращаемое значение больше 0, то есть a-b
- Возвращаемое значение равно 0, то есть a-b = 0, а позиции a и b остаются неизменными.
31. Отличие стрелочных функций от обычных функций
function data(a,b){
return a-b
};
var data = (a,b)=>a-b;
A, функция стрелки является анонимной функцией, не может использоваться в качестве конструктора, не может использовать New
let FunConstructor = () => {
console.log('lll');
}
let fc = new FunConstructor();//报错
б, стрелочная функция не привязана к аргументам, заменена параметрами REST...
function A(a){
console.log(arguments);
}
A(1,2,3,4,5,8); // [1, 2, 3, 4, 5, 8, callee: ƒ, Symbol(Symbol.iterator): ƒ]
let B = (b)=>{
console.log(arguments);
}
B(2,92,32,32); // Uncaught ReferenceError:arguments is not defined
let C = (...c) => {
console.log(c);
}
C(3,82,32,11323); // [3, 82, 32, 11323]
в) стрелочная функция не привязывает this и захватывает значение this контекста, в котором оно находится, как собственное значение this.
var obj = {
a: 10,
b: () => {
console.log(this.a); // undefined
console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
},
c: function() {
console.log(this.a); // 10
console.log(this); // {a: 10, b: ƒ, c: ƒ}
}
}
obj.b();
obj.c();
г. Когда стрелочная функция вызывает функцию через метод call() или apply(), передается только один параметр, который на это не влияет.
let obj2 = {
a: 10,
b: function(n) {
let f = (n) => n + this.a;
return f(n);
},
c: function(n) {
let f = (n) => n + this.a;
let m = {
a: 20
};
return f.call(m,n);
}
};
console.log(obj2.b(1)); // 11
console.log(obj2.c(1)); // 11
е. Стрелочные функции не имеют атрибута прототипа.
var a = ()=>{
return 1;
}
function b(){
return 2;
}
console.log(a.prototype); // undefined
console.log(b.prototype); // {constructor: ƒ}
Оригинальный адрес:GitHub.com/gap/is…