(1) 执行上下文
其实就是在代码执行过程中,为其确定一个适当的执行顺序
包括:
- 全局环境下的变量定义、函数声明
- 局部环境下的变量定义、函数声明,this和arguments的确定
(2) this
this的值在执行时才能确认值,定义时无法确认
包括:
- a. 作为构造函数执行:指向该构造函数的实例对象
- b. 作为对象属性执行
- c. 作为普通函数执行
- d. call,apply,bind
- e. 箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。
(3)作用域
变量和函数的可访问范围
包括:
- a. 没有块级作用域,只有函数和全局作用域
- b. 作用域链
- b. 闭包的两个场景
- d. 词法作用域
(4) 闭包
包括:
a. 函数作为返回值
function f1(){
var a = 100;
return function(){
console.log(a)
}
}
var f2 = f1();
var a = 200;
f2();
b. 函数作为参数来传递
function f1(){
var a = 100;
return function(){
console.log(a)
}
}
var f2 = f1();
function f3(fn){
var a = 200;
fn():
}
f3(f2)
闭包特性
- (1) 闭包可以读取函数内部变量
- (2) 将函数内部变量的值始终保存在内存中
(5) 什么是异步?
不阻塞后面程序的进程
(6) 前端使用异步的场景:
包括:
- a. 定时任务:setTimeout, setInterval
- b. 网络请求:ajax请求,动态<img>加载
- c. 事件绑定
(7) DOM的本质
DOM的本质是为了操作文档出现的API,浏览器把拿到的html代码,结构化一个浏览器能识别并且js可操作的一个模型而已
(8) 请描述一下 cookie,sessionStorage和localStorage的区别
回答点:容量、是否会携带到ajax中,API易用性
包括:
- a. cookie只有4kb,而sessionStorage和localStorage最大容量5M
- b. cookie每次都会携带到ajax中,而sessionStorage和localStorage不会
- c. sessionStorage和localStorage用起来比较简单,getItem,setItem就可以
- d. sessionStorage在会话结束后,就会清理,locationStorage需要手动清理,不会自动清理
(9) AMD
包括:
- a. require.js
- b. 全局 define 函数
- c. 全局 require 函数
- d. 依赖JS会自动、异步加载、按需加载
(10) CommonJS
nodeJS模块化规范,现在被大量用于前端
(11) AMD和CommonJS使用场景
- a. 需要异步加载JS,使用AMD
- b. 使用 npm 之后建议使用 CommonJS
(12) 页面加载过程:从输入url到得到html的详细过程
包括:
(1) DNS解析
- a. 浏览器根据 DNS 服务器得到域名的 IP 地址
- b. 向这个 IP 的机器发送 http 请求
- c. 服务器收到请求,处理并返回
- d. 浏览器得到返回内容
(2) TCP三次握手
- a. 发送端首先发送一个数据包给接收端
- b. 接收端收到后回传一个数据包确认收到
- c. 发送端发送一个数据包给接收端表示握手结束
(3) 浏览器发送HTTP请求
(4) 服务器处理请求并返回HTTP报文
(5) 浏览器渲染页面过程
- a. 根据 HTML 结构生成 DOM Tree
- b. 根据 CSS 生成 CSSOM
- c. 将 DOM 和 CSSOM 整合成 RenderTree
- d. 根据 RenderTree 开始渲染和展示
- e. 遇到 <script> 时,会执行并阻塞渲染
(13) 性能优化
从哪里入手 ?
- 加载页面和静态资源
- 页面渲染
- 页面操作
加载页面和静态资源:
a. 静态资源的压缩合并
b. 使用 CDN 让资源加载更快
c. 使用 SSR 后端渲染,直接输出在HTML中
渲染优化:
a. CSS 放前面,JS放在后面
b. 懒加载(图片懒加载,下拉加载更多)
c. 减少 DOM 查询,对 DOM 查询做缓存
d. 减少 DOM 操作,多个操作尽量合并在一起
e. 事件节流
f. 尽早执行操作(如:DOMContentLoaded)
(14) XSS-安全性
XSS:通过插入恶意代码,获取cookie
预防:
- a. 前端替换关键字:
- b. 后端替换
(15) XSRF
伪造成受信任的用户来发送请求
预防:
- a. 使用验证码
- b. 重要数据交互采用POST进行接收
(16) 如何看待加班?
加班就像借钱,救急不救穷
(17) 谈谈你的缺点:
说一下你最近在学啥就可以了
(18) 如何理解BOM
即Brower Object Model 浏览器对象模型,表示一个浏览器实例
包括:
- a. window 对象
- b. location 对象
- d. navigator 对象
- e. screed 对象
- f. history对象
(19) 如何理解 JSON
JSON其实就是一个 JS 对象
包括:
- a. stringify,把对象变为字符串
- b. parse,把字符串变为对象
(20) 请你说说JS这门语言中不好的地方:
- (1) 全局变量带来的问题
- (2) 作用域:没有块级作用域
- (3) 自动插入分号机制
- (4) parseInt('16 tons')没有提示有文字
- (5) hasOwnProperty 只是一个方法,而不是运算符,容易被覆盖
(21):跨域AJAX解决方案:
为什么会有跨域:
- a. 浏览器的同源策略,两个文件必须有相同的协议、端口和主机,才能互相操作
(22) 跨越解决方案:
JSONP:
利用script标签的src属性实现
特点:
- a. 只支持GET请求
- b. 对老式浏览器有优势
原理:
浏览器创建一个<script>标签,利用<script>标签的src属性发送跨域请求,服务器收到请求,并返回一个函数,函数入参即为返回的值,浏览器接收到这个函数并执行,浏览器再删除第一步创建的<script>标签即可
实现代码:
function getJsonp(){
var tag = document.createElement('script');
tag.src = 'http://tkq2.com:8000/test?jsonpcallback=myfunc';
document.head.appendChild(tag);
document.head.removeChild(tag);
}
function myFun(list){
console.log(list)
}
CORS 跨域资源共享
原理:设置响应头,是的浏览器允许跨域请求,主要是服务端工作(Access-Control-Allow-Origin)
设置AJAX中withCredentials,即可发送cookie
(23) 手写一个深度遍历
function deepClone(data){
var t = Object.prototype.toString.call(data),
o;
if ( t == "[object Array]" ){
o = [];
} else if ( t = "[object Object]" ){
o = {};
} else if( t = "[object Date]" ) {
return new Date(data.getTime());
} else if ( t = "[object RegExp]" ){
var flags = [];
if ( data.global ){
flags.push('g');
}
if ( data.multiline ){
flags.push('m');
}
if ( data.ignoreCase ){
flags.push('i');
}
return new RegExp(data.source, flags.join(''))
} else if (data.nodeType && 'cloneNode' in data){
return data.cloneNode(true);
} else {
return data;
}
if ( t == "[object Array]" ){
for (var i = 0, len = data.length; i < len; i++ ){
o.push(deepClone(data[i]))
}
} else if ( t == "[object Object]" ){
for ( i in data ){
o[i] = deepClone(data[i])
}
}
return o;
}
(24) script标签放在body底部原因:
影响 DomContentLoad和load时间,进而影响依赖他们的代码的执行的开始时间
(25) 你怎么看待前后端分离?
前后端分离,是为了批次更好!
其实,它是一种web应用的架构模式
交互形式:
- a. 前后端之间通过HTTP请求进行交互,前端获取到数据后,进行页面的渲染
代码组织方式 - b. 代码分离
开发模式: - c. 前后端互相不依赖,并行开发
(26) 为什么要前后端分离?
打造更好的前后端团队
提升代码开发效率,解耦前后端
增强代码可维护性
(27) JS模块化核心思想
- a. 拆分:将JS代码按功能逻辑拆分成多个可复用的JS代码模块
- b. 加载:如何将模块进行按需加载和输出,实现各个模块之间通信
- c. 依赖管理:管理模块之间的依赖
(28) 怎么做的技术选型?
技术:
- a. 此技术在业内是否已开始普及
- b. 是否有很好的被维护,生命周期要长
业务:根据业务选择对应的技术 - a. 初创企业要求“灵活”
- b. 成熟企业要求“可靠”
人
(29) call()和apply():
作用相同,区别仅仅在于接收参数的方式不同,call()的第二个参数必须逐个列举出来
(30) let
- a. 有块级作用域
- b. 不允许变量提升
- c. 有一个暂时性死区
- d. 不允许重复声明
(31) const命令
- a. 用来声明常量,声明后必须初始化赋值
- b. 有块级作用域
- c. 不存在变量提升
- d. 有一个暂时性死区
- e. 不允许重复声明
(32) 水平垂直居中方案:
使用绝对定位+transform实现:(不定高)
.parent{
position: relative;
}
.child{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
使用弹性布局(不定高)
.parent{
display: flex;
justify-content: center;
align-items: center;
}
使用 margin 偏移实现:(定高)
.parent {
position: relative;
}
.child {
width: 200px;
height: 200px;
position: absolute;
top: 50%;
left: 50%;
margin: -100px 0 0 -100px;
}
利用 margin auto 实现(定高)
.parent {
position: relative;
}
.child{
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
(33) 关键请求链
可视区域渲染完毕,对于用户来说可用时,必须加载的资源请求队列,叫做关键请求链
优化方案:
利用 LocalStorage 对部分请求的数据和结果进行缓存
原理:
- a. 对于缓存的JS文件通过后缀来设置独一无二的版本标识
- b. 后端每次传一份资源配置文件,前端根据这个配置文件和LS中缓存的文件进行版本标识匹配,从而决定是利用LS缓存还是重新请求
(34) 找到数组中的最大值
Math.max.apply(Math,[1,2,3,4])
(35) 可以在某个整数范围内随机选择一个值
Math.floor(Math.random() * 10 + 1)
(36) defer,async
defer
: 是早 HTML4 中提出的,用于开启新的线程下载脚本文件,并使脚本在文档解析完(所有元素解析完成之后,DOMContentLoaded事件触发之前)成后执行
async
:是 HTML5 标准中提出的,用于异步下载脚本文件,下载完毕立即解释执行代码
(37) position
- absolute:绝对定位,相对于static定位以外的第一个父元素定位
- fixed:绝对定位,相对于浏览器窗口进行定位
- relative:相对定位,相对于其正常位置进行定位
- static:默认值,没有定位,元素出现在正常的流中
(38) TCP三次握手
- a. 发送端首先发送一个数据包给接收端
- b. 接收端收到后回传一个数据包确认收到
- c. 发送端发送一个数据包给接收端表示握手结束
(39) 通过匿名函数来模拟块级作用域
function outputNumbers(count){
var aaa;
(function(){
for (var i = 0; i < count; i++){
aaa = i;
}
})();
console.log(aaa)
}
outputNumbers(3);
(40) 创建一个作用域安全的构造函数
function Person(name, age, job){
if ( this instanceof Person){
this.name = name;
this.age = age;
this.job = job;
} else {
return new Person(name, age, job)
}
}
(41) 升序
function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
(42) 降序
function compare(value1, value2) {
if (value1 < value2) {
return 1;
} else if (value1 > value2) {
return -1;
} else {
return 0;
}
}
(43) arguments.callee 是一个指针,指向拥有这个 arguments 对象的函数
(44) 递归函数:
function factorial(num){
if ( num <= 1 ){
return 1;
} else {
return num * arguments.callee(num - 1)
}
}
(45) 原型链和继承
https://www.jianshu.com/p/a2a5a65fe347
(46) 算法相关:
判断一个单词是回文:
function check(str) {
return str == str.split('').reverse().join('');
}
不借助临时变量,进行两个整数的交换:
function swap(a , b) {
b = b - a;
a = a + b;
b = a - b;
return [a,b];
}
找出下列正数组的最大差值比如:
var arr = [1,2,3,4,5,-6,7,8,8,9,9,0]
var min = Math.min.apply(Math, arr);
var max = Math.max.apply(Math, arr);
随机生成指定长度的字符串
function randomString(n){
var str = 'abcdefghijklmnopqrstuvwxyz9876543210';
var tmp = '';
for (var i = 0; i < n; i++){
tmp += str.charAt(Math.floor(Math.random() * str.length))
}
return tmp;
}
随机获取数组中的元素
var arr = ['前端','后端','测试','视觉','运营','交互','产品']
function getRandomFromArr(arr){
return arr[Math.floor(Math.random() * arr.length)]
}
对象转为数组
var obj = {
0: 'qian',
1: 'long',
2: 'chu',
3: 'tian',
length: 4
}
[].slice.call(obj)
二叉树:
https://segmentfault.com/a/1190000000740261
(47) http-only
告之浏览器该 cookie 绝不能通过 JavaScript 的 document.cookie属性访问。设计该特征意在提供一个安全措施来帮助阻止通过 JavaScript 发起的跨站脚本攻击 (XSS) 窃取 cookie 的行为
(48)
caller
是返回一个对函数的引用,该函数调用了当前函数;
callee
是返回正在被执行的function函数,也就是所指定的function对象的正文。
(49) HTML Entity
htmlDecode:function (text){
//1.首先动态创建一个容器标签元素,如DIV
var temp = document.createElement("div");
//2.然后将要转换的字符串设置为这个元素的innerHTML(ie,火狐,google都支持)
temp.innerHTML = text;
//3.最后返回这个元素的innerText(ie支持)或者textContent(火狐,google支持),即得到经过HTML解码的字符串了。
var output = temp.innerText || temp.textContent;
temp = null;
return output;
}
(50)什么是浏览器的标准模式(standards mode)和怪异模式(quirks mode)
目前浏览器的排版引擎有三种模式:怪异模式(Quirks mode)
、接近标准模式(Almost standards mode)
、以及标准模式(Standards mode)
。在怪异模式下,排版会模拟 Navigator 4 与 Internet Explorer 5 的非标准行为。为了支持在网络标准被广泛采用前,就已经建好的网站,这么做是必要的。在标准模式下,行为即(但愿如此)由 HTML 与 CSS 的规范描述的行为。在接近标准模式下,只有少数的怪异行为被实现。
那么所谓标准模式,就一定都“标准”吗?答案当然是否定的,因为各个浏览器厂商实现标准的阶段不同,所以各个浏览器的“标准模式”之间也会有很大的不同。
Firefox、Safari、Chrome、Opera (自 7.5 以后)、 IE8 和 IE9 都有一个准标准模式。那么既然标准模式都不那么标准,准标准的模式肯定就更不标准了。
(51) 清除浮动 https://www.jianshu.com/p/b1fd83728fc0
(52) 如何要求容器在宽度自由很缩的情况下,A/B/C的宽度始终是1:1:1,
.div1 {
width: 100%;
height: 400px;
border: 1px solid #888;
flex-direction: row;
/**主要代码*/
display: flex;
/* align-items: center; */
/* justify-content: center; */
}
.div {
/* position:absolute; */
/* width:500px; */
flex-grow: 1;
border: 1px solid #888;
}
(53) 将 arguments 转为真正的数组
Array.prototype.slice.call(arguments);
(54) typeof 返回值:
undefined, null, boolean, number, string, object
(55)
浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。这个过程称为“重排”。完成重排后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。
改变颜色只会引起重绘,因为其没有改变元素的几何属性。
(56)
function test () {
for (var i = 0; i < 4; i++) {
setTimeout(function () {
console.log(i);
}, 0)
}
}
test();
让上面依次输出1,2,3,4
function test () {
for (var i = 0; i < 4; i++) {
(function(e){
setTimeout(function(){
console.log(e)
}, 0)
})(i)
}
}
test();
(57) 数据双向绑定原理:常见数据绑定的方案
(58) 监听数组的变化:https://zhuanlan.zhihu.com/p/27166404
(59) Vue 之所以引入了 Virtual DOM,更重要的原因是为了解耦 HTML 依赖,这带来两个非常重要的好处是:
不再依赖 HTML 解析器进行模版解析,可以进行更多的 AOT 工作提高运行时效率:通过模版 AOT 编译,Vue 的运行时体积可以进一步压缩,运行时效率可以进一步提升;
可以渲染到 DOM 以外的平台,实现 SSR、同构渲染这些高级特性,Weex 等框架应用的就是这一特性。
综上,Virtual DOM 在性能上的收益并不是最主要的,更重要的是它使得 Vue 具备了现代框架应有的高级特性。
(60) iframe有哪些缺点
- a. 页面样式调试麻烦,出现多个滚动条
- b. 浏览器后退按钮失效
- c. 过多会增加服务器的HTTP请求;
(61)link与@import的区别
- a. 加载顺序:link遇到即加载,@import等到页面全部被下载才加载
- b. import兼容性差
(62)
如果使用import方法对CSS进行导入,会导致某些页面在Windows 下的Internet Explorer出现一些奇怪的现象:以无样式显示页面内容的瞬间闪烁,这种现象称之为文档样式短暂失效(Flash of Unstyled Content),简称为FOUC.原因大致为:
- 1,使用import方法导入样式表。
- 2,将样式表放在页面底部
- 3,有几个样式表,放在html结构的不同位置。其实原理很清楚:当样式表晚于 结构性html 加载,当加载到此样式表时,页面将停止之前的渲染。此样式表被下载和解析后,将重新渲染页面,也就出现了短暂 的 花屏现象。解决方法:使用LINK标签将样式表放在文档HEAD中更多
(63):如果需要手动写动画,你认为最小时间间隔是多久,为什么?(阿里)
多数显示器默认频率是60Hz,即1秒刷新60次,所以理论上最小间隔为1/60*1000ms = 16.7ms
(64):常见display的值:
none, block, inline, inline-block, list-item,
table, inline-table, flex, inline-flex
(65) 事件代理/事件委托
本质是为了减少DOM操作来提高性能,原理:利用事件的冒泡原理来实现
(66) new 操作符经历过程:
- a. 创建一个新对象
- b. 将构造函数的作用域赋给新对象(this指向这个新对象)
- c. 执行构造函数中代码(为这个对象添加属性)
- d. 返回新对象
(67) AJAX原理:https://www.cnblogs.com/yhf286/p/4878351.html
ajax的工作原理相当于在用户和服务器之间加了一个中间层(AJAX引擎),使用户操作与服务器响应异步化。并不是所有的用户请求都提交给服务器,像—些数据验证和数据处理等都交给Ajax引擎自己来做, 只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。
Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。这其中最关键的一步就是从服务器获得请求数据。要清楚这个过程和原理,我们必须对 XMLHttpRequest有所了解。
(68) 异步加载JS的方式有哪些
- a. $(document).ready
- b. async="async"
- c. defer="defer"
- d. 动态创建<script>标签
(69)通用事件侦听器函数
function addEvent(element, type, handler){
if ( element.addEventListener ){
element.addEventListener(type, handler, false);
} else if ( element.attachEvent ){
element.attachEvent('on' + type, function(){
handler.call(element)
})
} else {
element['on' + type] = handler;
}
}
(70) 介绍一下你对浏览器内核的理解
渲染引擎和JS引擎,
渲染引擎:取得页面上内容进行展示
S引擎:解释和执行JS来实现网页的动态效果
最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎
(71) JS有哪几种数据类型
undefined
null
string
boolean
number
symbol
object
(72) webpack异步加载原理
webpack.ensure:把一些js模块给独立出一个个js文件,然后需要用到的时候,在创建一个script对象,加入到document.head对象中即可,浏览器会自动帮我们发起请求,去请求这个js文件,在写个回调,去定义得到这个js文件后,需要做什么业务逻辑操作
require.ensure这个函数是一个代码分离的分割线,表示 回调里面的require
是我们想要进行分割出去的
数组乱序
var arr = [1,2,3,45,6,7,9];
function randomArr(arr){
var res = [];
while ( arr.length ){
var index = Math.floor(Math.random() * (arr.length - 1))
res.push(arr[index]);
arr.splice(index, 1)
}
return res;
}
统计一个字符串出现最多的字母:
var str = 'wkdwfhiwsjkjwwhaiswhfbthwodiwsl';
var param = str.split('');
var res = [];
for( var i = 0; i < param.length; i++ ){
res[i] = 0;
for( var j = 0; j < param.length; j++ ){
if( param[j] == param[i] ){
res[i]++;
}
}
}
var maxRes = Math.max.apply(Math, res)
console.log(str.charAt(res.indexOf(maxRes)))
数组去重:
function unique(arr){
var res = [];
for ( var i = 0, len = arr.length; i < len; i++ ){
var isExit = res.indexOf(arr[i])
if ( isExit == -1 ){
res.push(arr[i])
}
}
return res;
}
var unique = function(arr){
var hasThis = {};
var data = [];
for ( var i = 0, len = arr.length; i < len; i++ ){
if( !hasThis[arr[i]] ){
hasThis[arr[i]] = true;
data.push(arr[i]);
}
}
return data;
}
function dedupe(array){
return Array.from(new Set(array));
}
(73) 冒泡排序:
随便从数组中拿一位数和后一位比较,如果是想从小到大排序,那么就把小的那一位放到前面,大的放在后面,简单来说就是交换它们的位置,如此反复的交换位置就可以得到排序的效果。
var arr = [3,1,4,2,5,21,6,15,63];
function sortA(arr){
for ( var i = 0; i < arr.length - 1; i++ ){
for ( var j = 0; j < arr.length - i - 1; j++){
if ( arr[j] < arr[j + 1] ){
var result = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = result;
}
}
}
return arr;
}
二分查找:
也为折半查找。首先要找到一个中间值,通过与中间值比较,大的放又,小的放在左边。再在两边中寻找中间值,持续以上操作,直到找到所在位置为止。
选择排序:
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾
//因为一次循环只能交换一个最大的值,所以需要再套一层for循环。
(74) Promsie原理
主要使用了观察者模式:
- a. 通过Promise.prototype.then和Promise.prototype.catch方法将观察者方法注册到被观察者Promise对象中,同时返回一个新的Promise对象,以便可以链式调用
- b. 被观察者管理内部pending,fulfilled和rejected的状态转变,同时通过构造函数中传递的resolve和reject方法以主动触发状态转变和通知观察者
这里你谈 promise 的时候,除了将他解决的痛点以及常用的 API 之外,最好进行拓展把 eventloop 带进来好好讲一下,microtask、macrotask 的执行顺序,如果看过 promise 源码,最好可以谈一谈 原生 Promise 是如何实现的。Promise 的关键点在于callback 的两个参数,一个是 resovle,一个是 reject。还有就是 Promise 的链式调用(Promise.then(),每一个 then 都是一个责任人)。
(75) debounce 去抖
就是一个事件如果频繁触发,会隔一段时间执行一次。
原理
/**
* @param fn {Function} 实际要执行的函数
* @param delay {Number} 延迟执行毫秒数
*
* @return {Function} 返回函数
*/
function debounce(fn, delay){
var timer;
return function(){
var content = this,
args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
fn.apply(content, args)
}, delay)
}
}
(76) throttle 函数节流
函数节流背后的思想是指某些代码不可以在没有间断的情况下连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行
原理:
/**
* @param fn {Function} 实际要执行的函数
* @param delay {Number} 执行间隔毫秒数
*
* @return {Function} 返回一个"节流函数"
*/
function throttle(fn, delay){
var last,
timer;
return function(){
var context = this,
args = arguments,
now = +new Date();
if ( (last && now < (last + delay) ) ){
clearTimeout(timer);
timer = setTimeout(function(){
last = now;
fn.apply(context, args)
}, delay)
} else {
last = now;
fn.apply(context, args);
}
}
}
(77) 浏览器页面资源加载优化过程与优化
当一个浏览器截获到一个页面请求后,将会按照顺序做下面事情
- a. 首先会将所有需要加载的资源进行分类
- b. 根据浏览器相关安全策略,决定资源的加载权限(通过页面HTTP请求头的Content-Security-Policy字段来限制)
- c. 对各个资源的加载优先顺序进行计算和排序(核心)
- d. 根据加载优先顺序来加载资源
(78) flex 弹性布局 https://www.jianshu.com/p/c351c5be9a2e
为跨浏览器而生的一种布局方式
确立主轴:
flex-derection:row | row-reverse | column | column-reverse
确立主轴分布:
justify-content:flex-start | flex-end | center | space-between | space-around
确立侧轴:
align-items:stretch | center | flex-start | flex-end | baseline
定义单个弹性项目:
align-self
弹性容器内是否拆行
flex-wrap:nowrap | warp | warp-reverse
确立元素出现顺序:
order
设置弹性盒子的扩展比率
flex-grow
指定了 flex 元素的收缩规则
flex-shrink
用于设置或检索弹性盒伸缩基准值
flex-basis
(79) BFC:
我这个元素里的子孙元素,不会影响外部元素的布局
产生 BFC 方式如下:
- a. float 的值不为 none
- b. overflow 的值不为 visible
- c. position 的值为 absolute,fixed
- d. display 的值为 table-cell,table-caption, inline-block中的任何一个
(80) 原生AJAX
var xhr = new XMLHttpRequest();
xhr.open('GET', '/api', false)
xhr.onreadystatechange = function() {
if( xhr.readyState == 4 ){
if ( xhr.status == 200 ) {
alert(xhr.responseText)
}
}
}
xhr.send(null);
包括:
- 2xx:表示成功处理:如 200
- 3xx:需要重定向,浏览器直接跳转
- 4xx:客户端请求错误,如404
- 5xx:服务端错误
行内元素和块元素区别:
行内元素:
- a. 设置宽高无效
- b. 对margin仅设置左右方向有效,上下无效;padding设置上下左右都有效,即会撑大空间
- c. 不会自动进行换行
块元素:
- a. 能够识别宽高
- b. margin和padding的上下左右均对其有效
- c. 可以自动换行
行内块元素:
- a. 能够识别宽高
- b. 不自动换行
- c. 默认排列方式为从左到右
border-size:
浏览器默认 content-box:标准盒子模型,在宽度和高度之外绘制元素的内边距和边框。
比如:元素宽度100px 设置了padding:0 10px; border:10px;
那么,元素最终宽度:100 + 10 * 2 + 10 * 2 = 140
border-box:IE盒子模型,通过从已设定的宽度和高度分别减去边框和内边距才能得到内容的宽度和高度。
比如:元素宽度100px 设置了padding:0 10px; border:10px;
那么,元素最终宽度:100px
设置的padding只会向内挤压内容区域的宽度
柯里化是这样的一个转换过程,把接受多个参数的函数变换成接受一个单一参数(注:最初函数的第一个参数)的函数,如果其他的参数是必要的,返回接受余下的参数且返回结果的新函数。
requireJS和webpack异步加载原理
requireJS实现原理
函数节流(throttle)与函数去抖(debounce)
前端需要注意哪些SEO?
- (1) 合理的title、description、keywords:搜索对这三项的权重逐个减少,title强调重点即可,description 把页面内容高度概括,keywords列举出重要关键词
- (2) 语义化的HTML代码,符合W3C规范
- (3) 重要内容HTML代码放在最前:搜索引擎抓取HTML顺序是从上到下,有的搜索引擎对抓取长度有限制,保证重要内容一定会被抓取
- (4) 重要内容不要用js输出:爬虫不会执行JS获取内容
- (5) 少用iframe:搜索引擎不会抓取 iframe 中的内容
- (6) 提高网站速度,网站速度是搜索引擎排序的一个重要指标
Web开发中会话跟踪的方法:
- (1) cookie
- (2) session
- (3) 隐藏input
HTML 全局属性有哪些:
class, data-*, dir, hidden, id, lang(元素内容的语言), style, title, translate
什么是web语义化,有什么好处?
web语义化包含了 HTML标签的语义化和CSS命名的语义化
好处:
- (1) 去掉样式后页面呈现清晰的结构
- (2) 盲人使用读屏器更好的阅读
- (3) 搜索引擎更好的理解页面,有利于收录
- (4) 使团队项目的可持续运作和维护
HTTP method
- (1) GET: 请求服务器发送某个资源
- (2) PUT: 让服务器用请求的主体部分来创建一个由所请求的URL命名的新文档,或者,如果那个URL已经存在的话,就用这个主体替代它。
- (3) POST: 向服务器输入数据
- (4) Options: 请求服务器告知其支持的各种功能。
- (5) Delete: 请求服务器删除请求url指定的资源
CSS 有哪些继承属性:
font,text-align,letter-spacing,word-spacing,
white-space,text-indet,ling-height,color,cursor
JS 有哪些方法定义对象
- (1) 对象字面量:var obj = {};
- (2) 构造函数:var obj = new Object();
- (3) Object.create(): var obj = Object.create(Object.prototype)
// 原生事件监听函数
function addListener(elem, type, handler){
if ( elem.addEventListener ){
elem.addEventListener(type, handler, false); // 第三个值: true: 事件在捕获阶段执行 false: 事件在冒泡阶段执行
return handler;
} else if ( elem.attachEvent ){
function wrapper(){
var event = window.event;
event.target = event.srcElement;
handler.call(elem, event);
}
elem.attachEvent('on' + type, wrapper);
return wrapper;
}
}
[1, [2, [ [3, 4], 5], 6]] => [1, 2, 3, 4, 5, 6] ?
var data = [1, [2, [ [3, 4], 5], 6]];
function flat(data, result){
for ( var i = 0; i < data.length; i++ ){
var d = data[i];
if ( typeof d == 'number' ){
result.push(d);
} else {
arguments.callee(d, result)
}
}
return result;
}
console.log(flat(data, []))
TypeScript和ES5, ES6的区别
TypeScript是 JavaScript 的超集。ES6是ES5的改进。
TypeScript 的价值并不是在于编写更少的代码,其价值在于编写更加安全的代码。从长远看来,它能帮我我们利用其工具识别问题并自动填充参数、属性、函数以及更多的东西,从而更有效率的编写出代码。
TypeScript在ES6之外还提供了:
- 类型
- 接口
- 未来 ES2016+ 特性
TypeScript 是JavaScript 类型化子集,它会被编译成原生的JavaScript
怎么管理异步: 回调函数、事件监听、观察者模式、promise、队列函数
session cookie区别 客户端存储:
Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
session 的生命周期
Session保存在服务器端。为了获得更高的存取速度,服务器一般把Session放在内存里。每个用户都会有一个独立的Session。如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。
Session在用户第一次访问服务器的时候自动创建
Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session“活跃(active)”了一次。
session 的有效期
由于会有越来越多的用户访问服务器,因此Session也会越来越多。为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。
Session的超时时间为maxInactiveInterval属性
Session对浏览器的要求
虽然Session保存在服务器,对客户端是透明的,它的正常运行仍然需要客户端浏览器的支持。这是因为Session需要使用Cookie作为识别标志。HTTP协议是无状态的,Session不能依据HTTP连接来判断是否为同一客户,因此服务器向客户端浏览器发送一个名为JSESSIONID的Cookie,它的值为该Session的id(也就是HttpSession.getId()的返回值)。Session依据该Cookie来识别是否为同一用户。
如果客户端浏览器将Cookie功能禁用,或者不支持Cookie怎么办?例如,绝大多数的手机浏览器都不支持Cookie。Java Web提供了另一种解决方案:URL地址重写。
前端框架的演变史:
- 最初的时代——web1.0
- 前端的春天——Ajax
- 前端的框架——MVC、MVP、MVVM
- MVC 的变种——FLux(单向数据流)
对于强制缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行比较缓存策略。
对于比较缓存,将缓存信息中的Etag和Last-Modified通过请求发送给服务器,由服务器校验,返回304状态码时,浏览器直接使用缓存。
same-value-equality:
不同之处在于,一是 +0不等于-0,二是NaN等于自身
+0 === -0 // true
NaN === NaN // false
Object.is(+0,-0) // false
Object.is(NaN,NaN) // true
Set数据结构:类似数组,但是成员的值都是唯一的,没有重复的值(add添加新值)
WeakSet: 和 Set 有两个不同
(1) WeakSet 的成员只能是对象,而不能是其他类型的值
(2) WeakSet 里面的引用不计入垃圾回收机制,如果其他对象不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存。
WeakSet 不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了。WeakSet的一个用处,是储存DOM节点,而不用担心这些节点从文档移除时,会引发内存泄漏
Map: 类似于对象,提供了 “值-值”的对应,让对象的键不止可以用字符串,可以使用任何值
const m = new Map();
m.set(o, 'content')
Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。这就解决了同名属性碰撞(clash)的问题,
WeakMap 和Map类似,也是用于生成键值对的集合
区别:
(1) WeakMap 只接受对象作为键名(null除外),不接受其他类型的值作为键名
(2) 其次,WeakMap 的键名所指向的对象,不计入垃圾回收机制
(3) 没有遍历操作(即没有key()、values()和entries()方法),也没有size属性
(4) 无法清空,即不支持clear方法。
webpack-dev-server主要是启动了一个使用express的Http服务器。它的作用主要是用来伺服资源文件。此外这个Http服务器和client使用了websocket通讯协议,原始文件作出改动后,webpack-dev-server会实时的编译,但是最后的编译的文件并没有输出到目标文件夹