# FE-interview
**Repository Path**: deepcc/FE-interview
## Basic Information
- **Project Name**: FE-interview
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2018-04-12
- **Last Updated**: 2020-12-20
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
- [FE-interview](#fe-interview)
- [$HTML, HTTP,web综合问题](#$html,-http,web综合问题)
- [敏捷开发的核心是什么](#敏捷开发的核心是什么)
- [浏览器内核](#浏览器内核)
- [页面渲染优化策略有哪些](#页面渲染优化策略有哪些)
- [`HTTP2.0`的升级有哪些 ](#http20的升级有哪些 )
- [VUE原理](#vue原理)
- [`双向绑定`其它实现方式](#双向绑定其它实现方式)
- [ES最新的规范](#es最新的规范)
- [2.5D是通过什么来实现](#25d是通过什么来实现)
- [职业规划及做了哪些准备](#职业规划及做了哪些准备)
- [常见排序算法的时间复杂度,空间复杂度](#常见排序算法的时间复杂度空间复杂度)
- [前端需要注意哪些SEO](#前端需要注意哪些seo)
- [web开发中会话跟踪的方法有哪些](#web开发中会话跟踪的方法有哪些)
- [``的`title`和`alt`有什么区别](#img的title和alt有什么区别)
- [doctype是什么,举例常见doctype及特点](#doctype是什么举例常见doctype及特点)
- [HTML全局属性(global attribute)有哪些](#html全局属性global-attribute有哪些)
- [什么是web语义化,有什么好处](#什么是web语义化有什么好处)
- [HTTP method](#http-method)
- [从浏览器地址栏输入url到显示页面的步骤(以HTTP为例)](#从浏览器地址栏输入url到显示页面的步骤以http为例)
- [HTTP request报文结构是怎样的](#http-request报文结构是怎样的)
- [HTTP response报文结构是怎样的](#http-response报文结构是怎样的)
- [如何进行网站性能优化](#如何进行网站性能优化)
- [什么是渐进增强](#什么是渐进增强)
- [HTTP状态码及其含义](#http状态码及其含义)
- [$CSS部分](#$css部分)
- [CSS选择器有哪些](#css选择器有哪些)
- [css sprite是什么,有什么优缺点](#css-sprite是什么有什么优缺点)
- [`display: none;`与`visibility: hidden;`的区别](#display-none与visibility-hidden的区别)
- [css hack原理及常用hack](#css-hack原理及常用hack)
- [specified value,computed value,used value计算方法](#specified-valuecomputed-valueused-value计算方法)
- [`link`与`@import`的区别](#link与@import的区别)
- [``display: block;``和``display: inline;``的区别](#display-block和display-inline的区别)
- [PNG,GIF,JPG的区别及如何选](#pnggifjpg的区别及如何选)
- [CSS有哪些继承属性](#css有哪些继承属性)
- [IE6浏览器有哪些常见的bug,缺陷或者与标准不一致的地方,如何解决](#ie6浏览器有哪些常见的bug缺陷或者与标准不一致的地方如何解决)
- [容器包含若干浮动元素时如何清理(包含)浮动](#容器包含若干浮动元素时如何清理包含浮动)
- [什么是FOUC?如何避免](#什么是fouc如何避免)
- [如何创建块级格式化上下文(block formatting context),BFC有什么用](#如何创建块级格式化上下文block-formatting-contextbfc有什么用)
- [display,float,position的关系](#displayfloatposition的关系)
- [外边距折叠(collapsing margins)](#外边距折叠collapsing-margins)
- [如何确定一个元素的包含块(containing block)](#如何确定一个元素的包含块containing-block)
- [stacking context,布局规则](#stacking-context布局规则)
- [如何水平居中一个元素](#如何水平居中一个元素)
- [如何竖直居中一个元素](#如何竖直居中一个元素)
- [$DOM部分](#DOM部分)
- [DOM元素e的e.getAttribute(propName)和e.propName有什么区别和联系](#dom元素e的egetattributepropname和epropname有什么区别和联系)
- [offsetWidth/offsetHeight,clientWidth/clientHeight与scrollWidth/scrollHeight的区别](#offsetwidthoffsetheightclientwidthclientheight与scrollwidthscrollheight的区别)
- [XMLHttpRequest通用属性和方法](#xmlhttprequest通用属性和方法)
- [focus/blur与focusin/focusout的区别与联系](#focusblur与focusinfocusout的区别与联系)
- [mouseover/mouseout与mouseenter/mouseleave的区别与联系](#mouseovermouseout与mouseentermouseleave的区别与联系)
- [sessionStorage,localStorage,cookie区别](#sessionstoragelocalstoragecookie区别)
- [javascript跨域通信](#javascript跨域通信)
- [$javascript概念部分](#javascript概念部分)
- [javascript有哪几种数据类型](#javascript有哪几种数据类型)
- [什么闭包,闭包有什么用](#什么闭包闭包有什么用)
- [javascript有哪几种方法定义函数](#javascript有哪几种方法定义函数)
- [应用程序存储和离线web应用](#应用程序存储和离线web应用)
- [客户端存储localStorage和sessionStorage](#客户端存储localstorage和sessionstorage)
- [cookie及其操作](#cookie及其操作)
- [javascript有哪些方法定义对象](#javascript有哪些方法定义对象)
- [===运算符判断相等的流程是怎样的](#===运算符判断相等的流程是怎样的)
- [==运算符判断相等的流程是怎样的](#==运算符判断相等的流程是怎样的)
- [对象到字符串的转换步骤](#对象到字符串的转换步骤)
- [对象到数字的转换步骤](#对象到数字的转换步骤)
- [<,>,<=,>=的比较规则](#==的比较规则)
- [+运算符工作流程](#运算符工作流程)
- [函数内部arguments变量有哪些特性,有哪些属性,如何将它转换为数组](#函数内部arguments变量有哪些特性有哪些属性如何将它转换为数组)
- [DOM事件模型是如何的,编写一个EventUtil工具类实现事件管理兼容](#dom事件模型是如何的编写一个eventutil工具类实现事件管理兼容)
- [评价一下三种方法实现继承的优缺点,并改进](#评价一下三种方法实现继承的优缺点并改进)
- [$javascript编程部分](#javascript编程部分)
- [请用原生js实现一个函数,给页面制定的任意一个元素添加一个透明遮罩(透明度可变,默认0.2),使这个区域点击无效,要求兼容IE8+及各主流浏览器,遮罩层效果如下图所示:](#请用原生js实现一个函数给页面制定的任意一个元素添加一个透明遮罩透明度可变默认02使这个区域点击无效要求兼容ie8及各主流浏览器遮罩层效果如下图所示)
- [请用代码写出(今天是星期x)其中x表示当天是星期几,如果当天是星期一,输出应该是"今天是星期一"](#请用代码写出今天是星期x其中x表示当天是星期几如果当天是星期一输出应该是今天是星期一)
- [下面这段代码想要循环延时输出结果0 1 2 3 4,请问输出结果是否正确,如果不正确,请说明为什么,并修改循环内的代码使其输出正确结果](#下面这段代码想要循环延时输出结果0-1-2-3-4请问输出结果是否正确如果不正确请说明为什么并修改循环内的代码使其输出正确结果)
- [现有一个Page类,其原型对象上有许多以post开头的方法(如postMsg);另有一拦截函数chekc,只返回ture或false.请设计一个函数,该函数应批量改造原Page的postXXX方法,在保留其原有功能的同时,为每个postXXX方法增加拦截验证功能,当chekc返回true时继续执行原postXXX方法,返回false时不再执行原postXXX方法](#现有一个page类其原型对象上有许多以post开头的方法如postmsg另有一拦截函数chekc只返回ture或false请设计一个函数该函数应批量改造原page的postxxx方法在保留其原有功能的同时为每个postxxx方法增加拦截验证功能当chekc返回true时继续执行原postxxx方法返回false时不再执行原postxxx方法)
- [完成下面的tool-tip](#完成下面的tool-tip)
- [编写javascript深度克隆函数deepClone](#编写javascript深度克隆函数deepclone)
- [补充代码,鼠标单击Button1后将Button1移动到Button2的后面](#补充代码鼠标单击button1后将button1移动到button2的后面)
- [网页中实现一个计算当年还剩多少时间的倒数计时程序,要求网页上实时动态显示"××年还剩××天××时××分××秒"](#网页中实现一个计算当年还剩多少时间的倒数计时程序要求网页上实时动态显示××年还剩××天××时××分××秒)
- [完成一个函数,接受数组作为参数,数组元素为整数或者数组,数组元素包含整数或数组,函数返回扁平化后的数组](#完成一个函数接受数组作为参数数组元素为整数或者数组数组元素包含整数或数组函数返回扁平化后的数组)
- [如何判断一个对象是否为数组](#如何判断一个对象是否为数组)
- [请评价以下事件监听器代码并给出改进意见](#请评价以下事件监听器代码并给出改进意见)
- [如何判断一个对象是否为函数](#如何判断一个对象是否为函数)
- [编写一个函数接受url中query string为参数,返回解析后的Object,query string使用application/x-www-form-urlencoded编码](#编写一个函数接受url中query-string为参数返回解析后的objectquery-string使用applicationx-www-form-urlencoded编码)
- [解析一个完整的url,返回Object包含域与window.location相同](#解析一个完整的url返回object包含域与windowlocation相同)
- [完成函数getViewportSize返回指定窗口的视口尺寸](#完成函数getviewportsize返回指定窗口的视口尺寸)
- [完成函数getScrollOffset返回窗口滚动条偏移量](#完成函数getscrolloffset返回窗口滚动条偏移量)
- [现有一个字符串richText,是一段富文本,需要显示在页面上.有个要求,需要给其中只包含一个img元素的p标签增加一个叫pic的class.请编写代码实现.可以使用jQuery或KISSY.](#现有一个字符串richtext是一段富文本需要显示在页面上有个要求需要给其中只包含一个img元素的p标签增加一个叫pic的class请编写代码实现可以使用jquery或kissy)
- [请实现一个Event类,继承自此类的对象都会拥有两个方法on,off,once和trigger](#请实现一个event类继承自此类的对象都会拥有两个方法onoffonce和trigger)
- [编写一个函数将列表子元素顺序反转](#编写一个函数将列表子元素顺序反转)
- [以下函数的作用是?空白区域应该填写什么](#以下函数的作用是空白区域应该填写什么)
- [编写一个函数实现form的序列化(即将一个表单中的键值序列化为可提交的字符串)](#编写一个函数实现form的序列化即将一个表单中的键值序列化为可提交的字符串)
- [使用原生javascript给下面列表中的li节点绑定点击事件,点击时创建一个Object对象,兼容IE和标准浏览器](#使用原生javascript给下面列表中的li节点绑定点击事件点击时创建一个object对象兼容ie和标准浏览器)
- [有一个大数组,var a = ['1', '2', '3', ...];a的长度是100,内容填充随机整数的字符串.请先构造此数组a,然后设计一个算法将其内容去重](#有一个大数组var-a-=-1-2-3-a的长度是100内容填充随机整数的字符串请先构造此数组a然后设计一个算法将其内容去重)
# FE-interview
个人收集的前端知识点、面试题和答案,参考答案仅代表个人观点,方便复习,目录如下,通过文档内搜索目录可快速定位章节
## $HTML, HTTP,web综合问题
### 敏捷开发的核心是什么
敏捷开发以`用户的需求进化`为核心,采用`迭代`、`循序渐进`的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备`可视`、`可集成`和`可运行使用`的特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。
[详细](https://baike.baidu.com/item/%E6%95%8F%E6%8D%B7%E5%BC%80%E5%8F%91/5618867)
### 浏览器内核
1. Trident(IE内核)
2. Gecko(Firefox内核)
3. Presto(Opera前内核) (已废弃)
4. Webkit(Safari内核,Chrome内核原型,开源)
5. Blink是一个由Google和Opera Software开发的浏览器排版引擎
[详细](https://baike.baidu.com/item/浏览器内核/10602413)
### 页面渲染优化策略有哪些
1. HTML文档结构层次尽量少,最好不深于六层;
1. 脚本尽量后放,放在`
center text
``` ## DOM部分 ### DOM元素e的e.getAttribute(propName)和e.propName有什么区别和联系 - e.getAttribute(),是标准DOM操作文档元素属性的方法,具有通用性可在任意文档上使用,返回元素在源文件中**设置的属性** - e.propName通常是在HTML文档中访问特定元素的**特性**,浏览器解析元素后生成对应对象(如a标签生成HTMLAnchorElement),这些对象的特性会根据特定规则结合属性设置得到,对于没有对应特性的属性,只能使用getAttribute进行访问 - e.getAttribute()返回值是源文件中设置的值,类型是字符串或者null(有的实现返回"") - e.propName返回值可能是字符串、布尔值、对象、undefined等 - 大部分attribute与property是一一对应关系,修改其中一个会影响另一个,如id,title等属性 - 一些布尔属性``的检测设置需要hasAttribute和removeAttribute来完成,或者设置对应property - 像`link`中href属性,转换成property的时候需要通过转换得到完整URL - 一些attribute和property不是一一对应如:form控件中``对应的是defaultValue,修改或设置value property修改的是控件当前值,setAttribute修改value属性不会改变value property ### offsetWidth/offsetHeight,clientWidth/clientHeight与scrollWidth/scrollHeight的区别 - offsetWidth/offsetHeight返回值包含**content + padding + border**,效果与e.getBoundingClientRect()相同 - clientWidth/clientHeight返回值只包含**content + padding**,如果有滚动条,也**不包含滚动条** - scrollWidth/scrollHeight返回值包含**content + padding + 溢出内容的尺寸** [Measuring Element Dimension and Location with CSSOM in Windows Internet Explorer 9](http://msdn.microsoft.com/en-us/library/ie/hh781509(v=vs.85).aspx)  ### XMLHttpRequest通用属性和方法 1. `readyState`:表示请求状态的整数,取值: - UNSENT(0):对象已创建 - OPENED(1):open()成功调用,在这个状态下,可以为xhr设置请求头,或者使用send()发送请求 - HEADERS_RECEIVED(2):所有重定向已经自动完成访问,并且最终响应的HTTP头已经收到 - LOADING(3):响应体正在接收 - DONE(4):数据传输完成或者传输产生错误 3. `onreadystatechange`:readyState改变时调用的函数 4. `status`:服务器返回的HTTP状态码(如,200, 404) 5. `statusText`:服务器返回的HTTP状态信息(如,OK,No Content) 6. `responseText`:作为字符串形式的来自服务器的完整响应 6. `responseXML`: Document对象,表示服务器的响应解析成的XML文档 7. `abort()`:取消异步HTTP请求 8. `getAllResponseHeaders()`: 返回一个字符串,包含响应中服务器发送的全部HTTP报头。每个报头都是一个用冒号分隔开的名/值对,并且使用一个回车/换行来分隔报头行 9. `getResponseHeader(headerName)`:返回headName对应的报头值 10. `open(method, url, asynchronous [, user, password])`:初始化准备发送到服务器上的请求。method是HTTP方法,不区分大小写;url是请求发送的相对或绝对URL;asynchronous表示请求是否异步;user和password提供身份验证 11. `setRequestHeader(name, value)`:设置HTTP报头 12. `send(body)`:对服务器请求进行初始化。参数body包含请求的主体部分,对于POST请求为键值对字符串;对于GET请求,为null ### focus/blur与focusin/focusout的区别与联系 1. focus/blur不冒泡,focusin/focusout冒泡 2. focus/blur兼容性好,focusin/focusout在除FireFox外的浏览器下都保持良好兼容性,如需使用事件托管,可考虑在FireFox下使用事件捕获elem.addEventListener('focus', handler, true) 3. 可获得焦点的元素: 1. window 2. 链接被点击或键盘操作 3. 表单空间被点击或键盘操作 4. 设置`tabindex`属性的元素被点击或键盘操作 ### mouseover/mouseout与mouseenter/mouseleave的区别与联系 1. mouseover/mouseout是标准事件,**所有浏览器都支持**;mouseenter/mouseleave是IE5.5引入的特有事件后来被DOM3标准采纳,现代标准浏览器也支持 2. mouseover/mouseout是**冒泡**事件;mouseenter/mouseleave**不冒泡**。需要为**多个元素监听鼠标移入/出事件时,推荐mouseover/mouseout托管,提高性能** 3. 标准事件模型中event.target表示发生移入/出的元素,**vent.relatedTarget**对应移出/如元素;在老IE中event.srcElement表示发生移入/出的元素,**event.toElement**表示移出的目标元素,**event.fromElement**表示移入时的来源元素 例子:鼠标从div#target元素移出时进行处理,判断逻辑如下:{1}{2}
'); console.log(t.format('http://www.alibaba.com', 'Alibaba', 'Welcome')); })(); ``` define部分定义一个简单的模板类,使用{}作为转义标记,中间的数字表示替换目标,format实参用来替换模板内标记 横线处填: 1. ``Array.prototype.slice.call(arguments, 0)`` 2. ``/\{\s*(\d+)\s*\}/g`` ### 编写一个函数实现form的序列化(即将一个表单中的键值序列化为可提交的字符串) ### 使用原生javascript给下面列表中的li节点绑定点击事件,点击时创建一个Object对象,兼容IE和标准浏览器 ``` Object: { "index": 1, "name": "111", "link": "http://1111" } ``` script: ``` var EventUtil = { getEvent: function (event) { return event || window.event; }, getTarget: function (event) { return event.target || event.srcElement; }, // 返回注册成功的监听器,IE中需要使用返回值来移除监听器 on: function (elem, type, handler) { if (elem.addEventListener) { elem.addEventListener(type, handler, false); return handler; } else if (elem.attachEvent) { function wrapper(event) { return handler.call(elem, event); }; elem.attachEvent('on' + type, wrapper); return wrapper; } }, off: function (elem, type, handler) { if (elem.removeEventListener) { elem.removeEventListener(type, handler, false); } else if (elem.detachEvent) { elem.detachEvent('on' + type, handler); } }, preventDefault: function (event) { if (event.preventDefault) { event.preventDefault(); } else if ('returnValue' in event) { event.returnValue = false; } }, stopPropagation: function (event) { if (event.stopPropagation) { event.stopPropagation(); } else if ('cancelBubble' in event) { event.cancelBubble = true; } } }; var DOMUtil = { text: function (elem) { if ('textContent' in elem) { return elem.textContent; } else if ('innerText' in elem) { return elem.innerText; } }, prop: function (elem, propName) { return elem.getAttribute(propName); } }; var nav = document.getElementById('nav'); EventUtil.on(nav, 'click', function (event) { var event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); var children = this.children; var i, len; var anchor; var obj = {}; for (i = 0, len = children.length; i < len; ++i) { if (children[i] === target) { obj.index = i + 1; anchor = target.getElementsByTagName('a')[0]; obj.name = DOMUtil.text(anchor); obj.link = DOMUtil.prop(anchor, 'href'); } } alert('index: ' + obj.index + ' name: ' + obj.name + ' link: ' + obj.link); }); ``` ### 有一个大数组,var a = ['1', '2', '3', ...];a的长度是100,内容填充随机整数的字符串.请先构造此数组a,然后设计一个算法将其内容去重 ``` /** * 数组去重 **/ function normalize(arr) { if (arr && Array.isArray(arr)) { var i, len, map = {}; for (i = arr.length; i >= 0; --i) { if (arr[i] in map) { arr.splice(i, 1); } else { map[arr[i]] = true; } } } return arr; } /** * 用100个随机整数对应的字符串填充数组。 **/ function fillArray(arr, start, end) { start = start == undefined ? 1 : start; end = end == undefined ? 100 : end; if (end <= start) { end = start + 100; } var width = end - start; var i; for (i = 100; i >= 1; --i) { arr.push('' + (Math.floor(Math.random() * width) + start)); } return arr; } var input = []; fillArray(input, 1, 100); input.sort(function (a, b) { return a - b; }); console.log(input); normalize(input); console.log(input); ``` 参考: [https://github.com/qiu-deqing/FE-interview](https://github.com/qiu-deqing/FE-interview)