借用神剧《权游》的名句:“凛冬将至!”,互联网寒冬已然来临,这一年以来keep/滴滴/京东/腾讯/华为等大厂裁人事件不断爆出!惊醒着头发慢慢脱落、变少的咱们,是时候闭关修炼了!javascript
本文为前端面试基础篇,将以 面试题 && 答案【参考 (๑¯∀¯๑)】的形式,闭关修炼,但愿你查漏补缺,完善你的知识体系!css
面试,咱们是认真的!
JavaScript 篇
1. JavaScript有⼏种类型的值
栈:原始数据类型( Undefined , Null , Boolean , Number 、 String )
堆:引⽤数据类型(对象、数组和函数)
两种类型的区别是:存储位置不一样
原始数据类型直接存储在栈( stack )中的简单数据段,占据空间⼩、⼤⼩固定,属于被频 繁使⽤数据,因此放⼊栈中存储;
引⽤数据类型存储在堆( heap )中的对象,占据空间⼤、⼤⼩不固定,若是存储在栈中,将会 影响程序运⾏的性能;引⽤数据类型在栈中存储了指针,该指针指向堆中该实体的起始地 址。当解释器寻找引⽤值时,会⾸先检索其 在栈中的地址,取得地址后从堆中得到实体
2. 介绍JavaScript有哪些内置对象
Object 是 JavaScript 中全部对象的⽗对象
数据封装类对象: Object 、 Array 、 Boolean 、 Number 和 String
其余对象: Function 、 Arguments 、 Math 、 Date 、 RegExp 、 Error
3. null,undefined 的区别
undefined 表示不存在这个值
undefined : 是⼀个表示"⽆"的原始值或者说表示"缺乏值",就是此处应该有⼀个值,但 是尚未定义。 例如变量被声明了,但没有赋值时,就等于 undefined
null 表示⼀个对象被定义了,值为“空值”
null : 是⼀个对象(空对象, 没有任何属性和⽅法) 例如做为函数的参数,表示该函数的参数不是对象; 在验证 null 时,⼀定要使⽤ === ,由于 == ⽆法分别 null 和 undefined
4. 什么是事件代理
事件代理( Event Delegation ),⼜称之为事件委托。是 JavaScript 中绑定事件的常⽤技巧。顾名思义,“事件代理”便是把本来须要绑定的事件委托给⽗元素,让⽗元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。
使⽤事件代理的好处是:
能够提⾼性能
能够⼤量节省内存占⽤
减小事件注册,⽐如在 table 上代理全部 td 的 click 事件
5. 同步和异步的区别
同步:浏览器访问服务器请求,⽤户看获得⻚⾯刷新,从新发请求,等请求完,⻚⾯刷新, 新内容出现,⽤户看到新内容,进⾏下⼀步操做
异步:浏览器访问服务器请求,⽤户正常操做,浏览器后端进⾏请求。等请求完,⻚⾯不 刷新,新内容也会出现,⽤户看到新内容
6. defer 和 async
defer 并⾏加载 js ⽂件,会按照⻚⾯上 script 标签的顺序执⾏
async 并⾏加载 js ⽂件,下载完成⽴即执⾏,不会按照⻚⾯上 script 标签的顺序执 ⾏
7. 什么是⾯向对象编程和⾯向过程编程
⾯向过程就是分析出解决问题所须要的步骤,而后⽤函数把这些步骤⼀步⼀步实现,使⽤ 的时候⼀个⼀个依次调⽤就能够了
⾯向对象是把构成问题事务分解成各个对象,建⽴对象的⽬的不是为了完成⼀个步骤,⽽ 是为了描叙某个事物在整个解决问题的步骤中的⾏为 ⾯向对象是以功能来划分问题,⽽不是步骤
8. ⾯向对象编程思想
9. Javascript中callee和caller的做⽤?
caller 是返回⼀个对函数的引⽤,该函数调⽤了当前函数;
callee 是返回正在被执⾏的 function 函数,也就是所指定的 function 对象的正⽂
10. 事件的各个阶段
1:捕获阶段 ---> 2:⽬标阶段 ---> 3:冒泡阶段
document ---> target ⽬标 ----> document
由此, addEventListener 的第三个参数设置为 true 和 false 的区别已经⾮常清晰了
true 表示该元素在事件的“捕获阶段”(由外往内传递时)响应事件
false 表示该元素在事件的“冒泡阶段”(由内向外传递时)响应事件
11. 闭包
闭包就是可以读取其余函数内部变量的函数
闭包是指有权访问另⼀个函数做⽤域中变量的函数,建立闭包的最常⻅的⽅式就是在⼀个 函数内建立另⼀个函数,经过另⼀个函数访问这个函数的局部变量,利⽤闭包能够突破做⽤链域
闭包的特性:
函数内再嵌套函数
内部函数能够引⽤外层的参数和变量
参数和变量不会被垃圾回收机制回收
说说你对闭包的理解 java
使⽤闭包主要是为了设计私有的⽅法和变量。闭包的优势是能够避免全局变量的污染,缺点是闭包会常驻内存,会增⼤内存使⽤量,使⽤不当很容易形成内存泄露。在js中,函数即 闭包,只有函数才会产⽣做⽤域的概念node
闭包的最⼤⽤处有两个,⼀个是能够读取函数内部的变量,另⼀个就是让这些变量始终保持在内存中ios
闭包的另⼀个⽤处,是封装对象的私有属性和私有⽅法nginx
好处:可以实现封装和缓存等;es6
坏处:就是消耗内存、不正当使⽤会形成内存溢出的问题 使⽤闭包的注意点web
因为闭包会使得函数中的变量都被保存在内存中,内存消耗很⼤,因此不能滥⽤闭包,否 则会形成⽹⻚的性能问题,在IE中可能致使内存泄露
解决⽅法是,在退出函数以前,将不使⽤的局部变量所有删除
12. 说说你对做⽤域链的理解
做⽤域链的做⽤是保证执⾏环境⾥有权访问的变量和函数是有序的,做⽤域链的变量只能 向上访问,变量访问到 window 对象即被终⽌,做⽤域链向下访问变量是不被容许的
简单的说,做⽤域就是变量与函数的可访问范围,即做⽤域控制着变量与函数的可⻅性和 ⽣命周期
13. JavaScript原型,原型链 ? 有什么特色?
每一个对象都会在其内部初始化⼀个属性,就是 prototype (原型),当咱们访问⼀个对象的属性时
若是这个对象内部不存在这个属性,那么他就会去 prototype ⾥找这个属性,这个 prototype ⼜会有⾃⼰的 prototype ,因而就这样⼀直找下去,也就是咱们平时所说的原型链的概念
关系: instance.constructor.prototype = instance._proto _
特色:
JavaScript 对象是经过引⽤来传递的,咱们建立的每一个新对象实体中并无⼀份属于 ⾃⼰的原型副本。当咱们修改原型时,与之相关的对象也会继承这⼀改变
当咱们须要⼀个属性的时, Javascript 引擎会先看当前对象中是否有这个属性, 若是没有的就会查找他的 Prototype 对象是否有这个属性,如此递推下去,⼀直检索到 Object 内 建对象
14. Javascript如何实现继承?
构造继承
原型继承
实例继承
拷⻉继承
原型 prototype 机制或 apply 和 call ⽅法去实现较简单,建议使⽤构造函数与原型混合⽅式
function Parent ( ) {
this .name = 'wang' ; }
function Child ( ) {
this .age = 28 ; }
Child.prototype = new Parent();
var demo = new Child();
console .log(demo.age);
console .log(demo.name);
复制代码
15. javascript有哪些⽅法定义对象
对象字⾯量: var obj = {};
构造函数: var obj = new Object();
Object.create(): var obj = Object.create(Object.prototype);
16. 谈谈This对象的理解
this 老是指向函数的直接调⽤者(⽽⾮间接调⽤者)
若是有 new 关键字, this 指向 new 出来的那个对象
在事件中, this 指向触发这个事件的对象,特殊的是, IE 中的 attachEvent 中的 this 老是指向全局对象 Window
17. new操做符具体⼲了什么呢?
建立⼀个空对象,而且 this 变量引⽤该对象,同时还继承了该函数的原型
属性和⽅法被加⼊到 this 引⽤的对象中
新建立的对象由 this 所引⽤,而且最后隐式的返回 this
18. 那些操做会形成内存泄漏?
内存泄漏指任何对象在您再也不拥有或须要它以后仍然存在
setTimeout 的第⼀个参数使⽤字符串⽽⾮函数的话,会引起内存泄漏
闭包使⽤不当
19. Ajax原理
Ajax 的原理简单来讲是在⽤户和服务器之间加了—个中间层( AJAX 引擎),经过 XmlHttpRequest 对象来向服务器发异步请求,从服务器得到数据,而后⽤ javascrip t 来操做 DOM ⽽更新⻚⾯。使⽤户操做与服务器响应异步化。这其中最关键的⼀步就是从服 务器得到请求数据
Ajax 的过程只涉及 JavaScript 、 XMLHttpRequest 和 DOM 。 XMLHttpRequest 是 aja x的核⼼机制
let xhr = null ;
xhr = new XMLHttpRequest()
xhr.open('get' , url, true )
xhr.send(null );
xhr.onreadystatechange = function ( ) {
if (xhr.readyState == 4 ){
if (xhr.status == 200 ){
success(xhr.responseText); } else {
fail && fail(xhr.status); } } }
复制代码
ajax 有那些优缺点?
优势:
经过异步模式,提高了⽤户体验.
优化了浏览器和服务器之间的传输,减小没必要要的数据往返,减小了带宽占⽤.
Ajax 在客户端运⾏,承担了⼀部分原本由服务器承担的⼯做,减小了⼤⽤户量下的服 务器负载。 Ajax 能够实现动态不刷新(局部刷新)
缺点:
安全问题 AJAX 暴露了与服务器交互的细节。
对搜索引擎的⽀持⽐较弱。 不容易调试。
20. 如何解决跨域问题?
先了解一下什么是同源策略
同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,若是缺乏了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即使两个不一样的域名指向同一个ip地址,也非同源。
同源策略限制如下几种行为:
Cookie、LocalStorage 和 IndexDB 没法读取
DOM 和 Js对象没法得到
AJAX 请求不能发送
经常使用跨域解决方案
经过jsonp跨域
跨域资源共享(CORS)
nginx代理跨域
nodejs中间件代理跨域
(PS:篇幅有限,具体用法自行百度)
21. 说说 event loop
⾸先, js 是单线程的,主要的任务是处理⽤户的交互,⽽⽤户的交互⽆⾮就是响应 DOM 的增删改,使⽤事件队列的形式,⼀次事件循环只处理⼀个事件
响应,使得脚本执⾏相对连续,因此有了事件队列,⽤来储存待执⾏的事件
那么事件队列的事件从哪⾥被 push 进来的呢。那就是另外⼀个线程叫事件触发线程作的事情了
它的做⽤主要是在定时触发器线程、异步 HTTP 请求线程 满⾜特定条件下的回调函数 push 到事件队列中,等待 js 引擎空闲的时候去 执⾏,固然js引擎执⾏过程当中有优先级之分,⾸先js引擎在⼀次事件循环中, 会先执⾏js线程的主任务,而后会去查找是否有微任务 microtask(promise) ,若是有那就优先执⾏微任务,若是没有,在去查找 宏任务 macrotask(setTimeout、setInterval) 进⾏执⾏
22. 什么是单线程,和异步的关系
单线程 - 只有⼀个线程,只能作⼀件事
缘由 - 避免 DOM 渲染的冲突
浏览器须要渲染 DOM
JS 能够修改 DOM 结构
JS 执⾏的时候,浏览器 DOM 渲染会暂停
两段 JS 也不能同时执⾏(都修改 DOM 就冲突了)
webworker ⽀持多线程,可是不能访问 DOM
解决⽅案 - 异步
23. 是否⽤过 jQuery 的 Deferred
使用jQuery Deferred以下:
总结以下:
没法改变 JS 异步和单线程的本质
只能从写法上杜绝 callback 这种形式
它是一种语法糖形式,可是解耦了代码
很好的体现:开放封闭原则
24. 异步编程的实现⽅式
回调函数
优势:简单、容易理解
缺点:不利于维护,代码耦合⾼
事件监听(采⽤时间驱动模式,取决于某个事件是否发⽣):
优势:容易理解,能够绑定多个事件,每一个事件能够指定多个回调函数
缺点:事件驱动型,流程不够清晰
发布/订阅(观察者模式)
相似于事件监听,可是能够经过‘消息中⼼ʼ,了解如今有多少发布者,多少订阅者
Promise对象
优势:能够利⽤then⽅法,进⾏链式写法;能够书写错误时的回调函数;
缺点:编写和理解,相对⽐较难
Generator函数
优势:函数体内外的数据交换、错误处理机制
缺点:流程管理不⽅便
async函数
优势:内置执⾏器、更好的语义、更⼴的适⽤性、返回的是Promise、结构清晰。
缺点:错误处理机制
25. 说说你对promise的了解
依照 Promise/A+ 的定义, Promise 有四种状态:
pending: 初始状态, ⾮ fulfilled 或 rejected.
fulfilled: 成功的操做.
rejected: 失败的操做.
settled: Promise 已被 fulfilled 或 rejected ,且不是 pending
另外, fulfilled 与 rejected ⼀起合称 settled
Promise 对象⽤来进⾏延迟( deferred ) 和异步( asynchronous ) 计算
Promise 的构造函数
let promise = new Promise (function (resolve, reject ) {
if (...) {
resolve(result);
} else {
reject(Error (errMessage));
}
});
复制代码
Promise 实例拥有 then ⽅法(具备 then ⽅法的对象,一般被称为 thenable )。 它的使⽤⽅法以下:
promise.then(onFulfilled, onRejected)
复制代码
接收两个函数做为参数,⼀个在 fulfilled 的时候被调⽤,⼀个在 rejected 的时候被 调⽤,接收参数就是 future , onFulfilled 对应 resolve , onRejected 对应 reject
26. 谈谈你对AMD、CMD的理解
CommonJS 是服务器端模块的规范, Node.js 采⽤了这个规范。 CommonJS 规范加载模 块是同步的,也就是说,只有加载完成,才能执⾏后⾯的操做。 AMD 规范则是⾮同步加载 模块,容许指定回调函数
AMD 推荐的⻛格经过返回⼀个对象作为模块对象, CommonJS 的⻛格经过对 module.exports 或 exports 的属性赋值来达到暴露模块对象的⽬的
es6模块 CommonJS、AMD、CMD
CommonJS 的规范中,每一个 JavaScript ⽂件就是⼀个独⽴的模块上下⽂( module context ),在这个上下⽂中默认建立的属性都是私有的。也就是说,在⼀个⽂件定义的 变量(还包括函数和类),都是私有的,对其余⽂件是不可⻅的。
CommonJS 是同步加载模块,在浏览器中会出现堵塞状况,因此不适⽤
AMD 异步,须要定义回调 define ⽅式
es6 ⼀个模块就是⼀个独⽴的⽂件,该⽂件内部的全部变量,外部⽆法获取。若是你希 望外部可以读取模块内部的某个变量,就必须使⽤ export 关键字输出该变量 es6 还可 以导出类、⽅法,⾃动适⽤严格模式
27. eval是作什么的
它的功能是把对应的字符串解析成 JS 代码并运⾏
应该避免使⽤ eval ,不安全,⾮常耗性能( 2 次,⼀次解析成 js 语句,⼀次执⾏)
由 JSON 字符串转换为JSON对象的时候能够⽤ eval,var obj =eval('('+ str +')')
28. javascript 代码中的"use strict";是什么意思
use strict 是⼀种 ECMAscript 5 添加的(严格)运⾏模式,这种模式使得 Javascript 在更严格的条件下运⾏,使 JS 编码更加规范化的模式,消除 Javascript 语法的⼀些不合 理、不严谨之处,减小⼀些怪异⾏为
29. js延迟加载的⽅式有哪些
defer 和 async 、动态建立 DOM ⽅式(⽤得最多)、按需异步载⼊ js
30. defer和async
defer 并⾏加载 js ⽂件,会按照⻚⾯上 script 标签的顺序执⾏
async 并⾏加载 js ⽂件,下载完成⽴即执⾏,不会按照⻚⾯上 script 标签的顺序执 ⾏
31. 渐进加强和优雅降级
渐进加强 :针对低版本浏览器进⾏构建⻚⾯,保证最基本的功能,而后再针对⾼级浏览器 进⾏效果、交互等改进和追加功能达到更好的⽤户体验。
优雅降级 :⼀开始就构建完整的功能,而后再针对低版本浏览器进⾏兼容
32. 说说严格模式的限制
变量必须声明后再使⽤
函数的参数不能有同名属性,不然报错
不能使⽤ with 语句
禁⽌ this 指向全局对象
33. 如何经过JS判断⼀个数组
instanceof ⽅法
instanceof 运算符是⽤来测试⼀个对象是否在其原型链原型构造函数的属性
let arr = [];
arr instanceof Array ;
复制代码
constructor ⽅法
constructor 属性返回对建立此对象的数组函数的引⽤,就是返回对象相对应的构造 函数
let arr = [];
arr.constructor == Array ;
复制代码
最简单的⽅法 这种写法,是 jQuery 正在使⽤的
Object .prototype.toString.call(value) == '[object Array]'
let isType = function (obj ) {
return Object .prototype.toString.call(obj).slice(8 ,-1 ); }
复制代码
let a = new Array (123 );
let b = new Date ();
console .log(Array .isArray(a));
console .log(Array .isArray(b));
复制代码
34. map与forEach的区别
forEach ⽅法,是最基本的⽅法,就是遍历与循环,默认有3个传参:分别是遍历的数组 内容 item 、数组索引 index 、和当前遍历数组 Array
map ⽅法,基本⽤法与 forEach ⼀致,可是不一样的,它会返回⼀个新的数组,因此在 callback须要有 return 值,若是没有,会返回 undefined
35. JS 数组和对象的遍历⽅式,以及⼏种⽅式的⽐较
for in 循环
for 循环
forEach
这⾥的 forEach 回调中两个参数分别为 value , index
forEach ⽆法遍历对象 IE不⽀持该⽅法; Firefox 和 chrome ⽀持
forEach ⽆法使⽤ break , continue 跳出循环,且使⽤ return 是跳过本次循 环
这两种⽅法应该⾮经常⻅且使⽤很频繁。但实际上,这两种⽅法都存在性能问题
在⽅式⼀中, for-in 须要分析出 array 的每一个属性,这个操做性能开销很⼤。⽤在 key 已知的数组上是⾮常不划算的。因此尽可能不要⽤ for-in ,除⾮你不清楚要处理哪 些属性,例如 JSON 对象这样的状况
在⽅式2中,循环每进⾏⼀次,就要检查⼀下数组⻓度。读取属性(数组⻓度)要⽐读局部 变量慢,尤为是当 array ⾥存放的都是 DOM 元素,由于每次读取都会扫描⼀遍⻚⾯上 的选择器相关元素,速度会⼤⼤下降
36. 数组去重⽅法总结
⽅法⼀、利⽤ES6 Set去重(ES6中最常⽤)
function unique (arr ) {
return Array .from(new Set (arr)) }
var arr = [1 ,2 ,3 ,4 ,5 ,,5 ,4 ,3 ,2 ,1 ]
console .log(unique(arr))
复制代码
⽅法⼆、利⽤for嵌套for,而后splice去重(ES5中最常⽤)
双层循环,外层循环元素,内层循环时⽐较值。值相同时,则删去这个值。
function unique (arr ) {
for (var i=0 ; i<arr.length; i++){
for (var j=i+1 ; j<arr.length; j++){
if (arr[i]==arr[j]){
arr.splice(j,1 );
j--;
}
}
}
return arr;
}
复制代码
⽅法3、利⽤indexOf去重
新建⼀个空的结果数组, for 循环原数组,判断结果数组是否存在当前元 素,若是有相同的值则跳过,不相同则 push 进数组
function unique (arr ) {
if (!Array .isArray(arr)) {
console .log('type error!' )
return
}
var array = [];
for (var i = 0 ; i < arr.length; i++) {
if (array .indexOf(arr[i]) === -1 ) {
array .push(arr[i])
}
}
return array;
}
复制代码
⽅法4、利⽤sort()
利⽤ sort() 排序⽅法,而后根据排序后的结果进⾏遍历及相邻元素⽐对
function unique (arr ) {
if (!Array .isArray(arr)) {
console .log('type error!' )
return ;
}
arr = arr.sort()
var arrry= [arr[0 ]];
for (var i = 1 ; i < arr.length; i++) {
if (arr[i] !== arr[i-1 ]) {
arrry.push(arr[i]); }
}
return arrry;
}
复制代码
⽅法5、利⽤对象的属性不能相同的特色进⾏去重
function unique (arr ) {
if (!Array .isArray(arr)) {
console .log('type error!' )
return
}
var arrry= [];
var obj = {};
for (var i = 0 ; i < arr.length; i++) {
if (!obj[arr[i]]) {
arrry.push(arr[i])
obj[arr[i]] = 1 } else {
obj[arr[i]]++
}
}
return arrry;
}
复制代码
⽅法6、利⽤includes
function unique (arr ) {
if (!Array .isArray(arr)) {
console .log('type error!' )
return
}
var array =[];
for (var i = 0 ; i < arr.length; i++) {
if ( !array.includes( arr[i]) ) {
array.push(arr[i]); }
}
return array
}
复制代码
⽅法7、利⽤hasOwnProperty
利⽤ hasOwnProperty 判断是否存在对象属性
function unique (arr ) {
var obj = {};
return arr.filter(function (item, index, arr ) {
return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof
})
}
复制代码
⽅法⼋、利⽤filter
function unique (arr ) {
return arr.filter(function (item, index, arr ) {
return arr.indexOf(item, 0 ) === index; });
}
复制代码
⽅法9、利⽤递归去重
function unique (arr ) {
var array= arr;
var len = array.length;
array.sort(function (a,b ) {
return a - b;
})
function loop (index ) {
if (index >= 1 ){
if (array[index] === array[index-1 ]){
array.splice(index,1 ); }
loop(index - 1 );
}
}
loop(len-1 );
return array;
}
复制代码
⽅法⼗、利⽤Map数据结构去重
建立⼀个空 Map 数据结构,遍历须要去重的数组,把数组的每⼀个元素做为 key 存到 Map 中。因为 Map 中不会出现相同的 key 值,因此最终获得的就 是去重后的结果
function arrayNonRepeatfy (arr ) {
let map = new Map ();
let array = new Array ();
for (let i = 0 ; i < arr.length; i++) {
if (map .has(arr[i])) {
map .set(arr[i], true );
} else {
map .set(arr[i], false );
array .push(arr[i]);
}
}
return array ;
}
复制代码
⽅法⼗⼀、利⽤reduce+includes
function unique (arr ) {
return arr.reduce((prev,cur ) => prev.includes(cur) ? prev : [...prev,cu
}
复制代码
⽅法⼗⼆、[...new Set(arr)]
[...new Set (arr)]
复制代码
37. 深浅拷⻉
浅拷⻉
深拷⻉
能够经过 JSON.parse(JSON.stringify(object)) 来解决
该⽅法也是有局限性的
会忽略 undefined
不能序列化函数
不能解决循环引⽤的对象
38. 防抖/节流
防抖和节流本质是不⼀样的。
防抖 是将屡次执⾏变为最后⼀次执⾏
节流 是将屡次执⾏变成每隔⼀段时间执⾏
39. 谈谈变量提高?
这是由于函数和变量提高的缘由
一般提高的解释是说将声明的代码移动到了顶部, 这其实没有什么错误,便于⼤家理解。
可是更准确的解释应该是:在⽣成执⾏环境时,会有两个阶段。
第⼀个阶段是建立的阶段,JS 解释器会找出须要提高的变量和函 数,而且给他们提早在内存中开辟好空间,函数的话会将整个函数存⼊内存中,变量 只声明而且赋值为 undefined
因此在第⼆个阶段,也就是代码执⾏阶段,咱们可 以直接提早使⽤
在提高的过程当中,相同的函数会覆盖上⼀个函数,而且函数优先于变量提高
40. let var const
let
容许你声明⼀个做⽤域被限制在块级中的变量、语句或者表达式
let绑定不受变量提高的约束,这意味着let声明不会被提高到当前
该变量处于从块开始到初始化处理的“暂存死区”
var
声明变量的做⽤域限制在其声明位置的上下⽂中,⽽⾮声明变量老是全局的
因为变量声明(以及其余声明)老是在任意代码执⾏以前处理的,因此在代码中的任意位 置声明变量老是等效于在代码开头声明
const
声明建立⼀个值的只读引⽤ (即指针)
基本数据当值发⽣改变时,那么其对应的指针也将发⽣改变,故形成 const 申明基本数 据类型时
再将其值改变时,将会形成报错, 例如 jsconst a = 3 ; a = 5
时 将会报错
可是若是是复合类型时,若是只改变复合类型的其中某个 Value 项时, 将仍是正常使⽤
41. 怎么判断两个对象相等?
能够转换为字符串来判断
JSON .stringify(obj1)==JSON .stringify(obj2);
复制代码
42. 谈⼀谈箭头函数与普通函数的区别?
函数体内的 this 对象,就是定义时所在的对象,⽽不是使⽤时所在的对象
不能够看成构造函数,也就是说,不可使⽤ new 命令,不然会抛出⼀个错误
不可使⽤ arguments 对象,该对象在函数体内不存在。若是要⽤,能够⽤ Rest 参数 代替
不可使⽤ yield 命令,所以箭头函数不能⽤做 Generator 函数
43. 谈⼀谈你理解的函数式编程
简单说,"函数式编程"是⼀种"编程范式"(programming paradigm),也就是如何编写程 序的⽅法论
它具备如下特性:闭包和⾼阶函数、惰性计算、递归、函数是"第⼀等公⺠"、只⽤"表达式"
44. ⽤过哪些设计模式?
⼯⼚模式:
⼯⼚模式解决了重复实例化的问题,但还有⼀个问题,那就是识别问题,由于根本⽆法
主要好处就是能够消除对象间的耦合,经过使⽤⼯程⽅法⽽不是 new 关键字
构造函数模式
使⽤构造函数的⽅法,即解决了重复实例化的问题,⼜解决了对象识别的问题,该模式 与⼯⼚模式的不一样之处在于
直接将属性和⽅法赋值给 this 对象;
Web 相关篇
1. 对web标准、可⽤性、可访问性的理解
可⽤性(Usability):产品是否容易上⼿,⽤户可否完成任务,效率如何,以及这过程当中 ⽤户的主观感觉可好,是从⽤户的⻆度来看产品的质量。可⽤性好意味着产品质量⾼,是 企业的核⼼竞争⼒
可访问性(Accessibility):Web内容对于残障⽤户的可阅读和可理解性
可维护性(Maintainability):⼀般包含两个层次,⼀是当系统出现问题时,快速定位并解 决问题的成本,成本低则可维护性好。⼆是代码是否容易被⼈理解,是否容易修改和加强 功能。
2. 说说从输⼊URL到看到⻚⾯发⽣的全过程,越详细越好
⾸先浏览器主进程接管,开了⼀个下载线程
而后进⾏HTTP请求(DNS查询、IP寻址等等),中间会有三次捂⼿,等待响应,开始下载 响应报⽂
将下载完的内容转交给Renderer进程管理
Renderer进程开始解析css rule tree和dom tree,这两个过程是并⾏的,因此⼀般我会把 link标签放在⻚⾯顶部
解析绘制过程当中,当浏览器遇到link标签或者script、img等标签,浏览器会去下载这些内 容,遇到时候缓存的使⽤缓存,不适⽤缓存的从新下载资源
css rule tree和dom tree⽣成完了以后,开始合成render tree,这个时候浏览器会进⾏ layout,开始计算每⼀个节点的位置,而后进⾏绘制
绘制结束后,关闭TCP链接,过程有四次挥⼿
3.说⼀下浏览器的缓存机制
浏览器缓存机制有两种,⼀种为强缓存,⼀种为协商缓存
对于强缓存,浏览器在第⼀次请求的时候,会直接下载资源,而后缓存在本地,第⼆次请 求的时候,直接使⽤缓存
对于协商缓存,第⼀次请求缓存且保存缓存标识与时间,重复请求向服务器发送缓存标识 和最后缓存时间,服务端进⾏校验,若是失效则使⽤缓存
协商缓存相关设置
Exprires :服务端的响应头,第⼀次请求的时候,告诉客户端,该资源何时会过 期。 Exprires 的缺陷是必须保证服务端时间和客户端时间严格同步。
Cache-control:max-age :表示该资源多少时间后过时,解决了客户端和服务端时间必 须同步的问题
If-None-Match/ETag :缓存标识,对⽐缓存时使⽤它来标识⼀个缓存,第⼀次请求的时 候,服务端会返回该标识给客户端,客户端在第⼆次请求的时候会带上该标识与服务端进 ⾏对⽐并返回 If-None-Match 标识是否表示匹配
Last-modified/If-Modified-Since :第⼀次请求的时候服务端返回 Last-modified 代表请求的资源上次的修改时间,第⼆次请求的时候客户端带上请求头 If-ModifiedSince ,表示资源上次的修改时间,服务端拿到这两个字段进⾏对⽐
4. HTTP状态码及其含义
1XX :信息状态码
100 Continue 继续,⼀般在发送 post 请求时,已发送了 http header 以后服务端
将返回此信息,表示确认,以后发送具体参数信息
2XX :成功状态码
200 OK 正常返回信息
201 Created 请求成功而且服务器建立了新的资源
202 Accepted 服务器已接受请求,但还没有处理
3XX :重定向
301 Moved Permanently 请求的⽹⻚已永久移动到新位置。
302 Found 临时性重定向。
303 See Other 临时性重定向,且老是使⽤ GET 请求新的 URI 。
304 Not Modified ⾃从上次请求后,请求的⽹⻚未修改过。
4XX :客户端错误
400 Bad Request 服务器⽆法理解请求的格式,客户端不该当尝试再次使⽤相同的内 容发起请求。
401 Unauthorized 请求未受权。
403 Forbidden 禁⽌访问。
404 Not Found 找不到如何与 URI 相匹配的资源。
5XX: 服务器错误
500 Internal Server Error 最常⻅的服务器端错误。
503 Service Unavailable 服务器端暂时⽆法处理请求(多是过载或维护)。
5. 介绍⼀下你对浏览器内核的理解?
主要分红两部分:渲染引擎( layout engineer 或 Rendering Engine )和 JS 引擎
渲染引擎:负责取得⽹⻚的内容( HTML 、 XML 、图像等等)、整理讯息(例如加⼊ CSS 等),以及计算⽹⻚的显示⽅式,而后会输出⾄显示器或打印机。浏览器的内核的不 同对于⽹⻚的语法解释会有不一样,因此渲染的效果也不相同。全部⽹⻚浏览器、电⼦邮件 客户端以及其它须要编辑、显示⽹络内容的应⽤程序都须要内核
JS 引擎则:解析和执⾏ javascript 来实现⽹⻚的动态效果
最开始渲染引擎和 JS 引擎并无区分的很明确,后来JS引擎愈来愈独⽴,内核就倾向于 只指渲染引擎
6. 请描述⼀下 cookies , sessionStorage 和 localStorage 的区别?
cookie 是⽹站为了标示⽤户身份⽽储存在⽤户本地终端(Client Side)上的数据(一般 通过加密)
cookie数据始终在同源的http请求中携带(即便不须要),记会在浏览器和服务器间来回 传递
sessionStorage 和 localStorage 不会⾃动把数据发给服务器,仅在本地保存
存储⼤⼩:
cookie 数据⼤⼩不能超过4k
sessionStorage 和 localStorage 虽然也有存储⼤⼩的限制,但⽐ cookie ⼤得 多,能够达到5M或更⼤
有期时间:
localStorage 存储持久数据,浏览器关闭后数据不丢失除⾮主动删除数据
sessionStorage 数据在当前浏览器窗⼝关闭后⾃动删除
cookie 设置的 cookie 过时时间以前⼀直有效,即便窗⼝或浏览器关闭
7. 为何利⽤多个域名来存储⽹站资源会更有效?
CDN 缓存更⽅便
突破浏览器并发限制
节约 cookie 带宽
节约主域名的链接数,优化⻚⾯响应速度
防⽌没必要要的安全问题
8. 重绘和回流(重排)是什么,如何避免?
DOM的变化影响到了元素的⼏何属性(宽⾼),浏览器从新计算元素的⼏何属性,其余元素 的⼏何
属性和位置也会受到影响,浏览器须要从新构造渲染树,这个过程称为重排,浏览器将受 到影响的部分
从新绘制到屏幕上的过程称为重绘。引发重排的缘由有
添加或者删除可⻅的DOM元素,
元素位置、尺⼨、内容改变,
浏览器⻚⾯初始化
浏览器窗⼝尺⼨改变,重排⼀定重绘,重绘不⼀定重排
减小重绘和重排的⽅法:
不在布局信息改变时作 DOM 查询
使⽤ cssText 或者 className ⼀次性改变属性
使⽤ fragment
对于屡次重排的元素,如动画,使⽤绝对定位脱离⽂档流,让他的改变不影响到其余元素
9. 常⻅web安全及防御原理
sql 注⼊原理
就是经过把 SQL 命令插⼊到 Web 表单递交或输⼊域名或⻚⾯请求的查询字符串,最终 达到欺骗服务器执⾏恶意的SQL命令
总的来讲有如下⼏点
永远不要信任⽤户的输⼊,要对⽤户的输⼊进⾏校验,能够经过正则表达式,或限制⻓ 度,对单引号和双 "-" 进⾏转换等 永远不要使⽤动态拼装SQL,可使⽤参数化的 SQL 或者直接使⽤存储过程进⾏数据查询存取
永远不要使⽤管理员权限的数据库链接,为每一个应⽤使⽤单独的权限有限的数据库链接
不要把机密信息明⽂存放,请加密或者 hash 掉密码和敏感的信息
XSS原理及防范
Xss(cross-site scripting) 攻击指的是攻击者往 Web ⻚⾯⾥插⼊恶意 html 标签或 者 javascript 代码。⽐如:攻击者在论坛中放⼀个看似安全的连接,骗取⽤户点击后, 窃取 cookie 中的⽤户私密信息;或者攻击者在论坛中加⼀个恶意表单,当⽤户提交表单 的时候,却把信息传送到攻击者的服务器中,⽽不是⽤户本来觉得的信任站点
XSS防范⽅法
⾸先代码⾥对⽤户输⼊的地⽅和变量都须要仔细检查⻓度和对 ”<”,”>”,”;”,”’” 等字符 作过滤;其次任何内容写到⻚⾯以前都必须加以encode,避免不⼩⼼把 html tag 弄出 来。这⼀个层⾯作好,⾄少能够堵住超过⼀半的XSS 攻击
XSS与CSRF有什么区别吗?
XSS 是获取信息,不须要提早知道其余⽤户⻚⾯的代码和数据包。 CSRF 是代替⽤户完成 指定的动做,须要知道其余⽤户⻚⾯的代码和数据包。要完成⼀次 CSRF 攻击,受害者必 须依次完成两个步骤
登陆受信任⽹站 A ,并在本地⽣成 Cookie
在不登出 A 的状况下,访问危险⽹站 B
CSRF的防护
服务端的 CSRF ⽅式⽅法不少样,但总的思想都是⼀致的,就是在客户端⻚⾯增长伪随机数
经过验证码的⽅法
10. WebSocket
因为 http 存在⼀个明显的弊端(消息只能有客户端推送到服务器端,⽽服 务器端不能主动推送到客户端),致使若是服务器若是有连续的变化,这时只 能使⽤轮询,⽽轮询效率太低,并不适合。因而 WebSocket 被发明出来
相⽐与 http 具备如下有点
⽀持双向通讯,实时性更强;
能够发送⽂本,也能够⼆进制⽂件;
协议标识符是 ws ,加密后是 wss ;
较少的控制开销。链接建立后, ws 客户端、服务端进⾏数据交换时,协议控制的数据包 头部较⼩。在不包含头部的状况下,服务端到客户端的包头只有 2~10 字节(取决于数据 包⻓度),客户端到服务端的的话,须要加上额外的4字节的掩码。⽽ HTTP 协议每次通讯 都须要携带完整的头部;
⽀持扩展。ws协议定义了扩展,⽤户能够扩展协议,或者实现⾃定义的⼦协议。(⽐如⽀ 持⾃定义压缩算法等)
⽆跨域问题。
11. ajax、axios、fetch区别 jQuery ajax
jQuery ajax
优缺点:
自己是针对 MVC 的编程,不符合如今前端 MVVM 的浪潮
基于原⽣的 XHR 开发, XHR 自己的架构不清晰,已经有了 fetch 的替代⽅案
JQuery 整个项⽬太⼤,单纯使⽤ ajax 却要引⼊整个 JQuery ⾮常的不合理(采起个性 化打包的⽅案⼜不能享受CDN服务)
axios 优缺点:
从浏览器中建立 XMLHttpRequest
从 node.js 发出 http 请求 ⽀持 Promise API
拦截请求和响应
转换请求和响应数据
取消请求
⾃动转换 JSON 数据
客户端⽀持防⽌ CSRF/XSRF
fetch
优缺点:
fetcht 只对⽹络请求报错,对 400 , 500 都当作成功的请求,须要封装去处理
fetch 默认不会带 cookie ,须要添加配置项
fetch 不⽀持 abort ,不⽀持超时控制,使⽤ setTimeout 及 Promise.reject 的实 现的超时控制并不能阻⽌请求过程继续在后台运⾏,形成了量的浪费
fetch 没有办法原⽣监测请求的进度,⽽XHR能够
12. 项⽬作过哪些性能优化?
减小 HTTP 请求数
减小 DNS 查询
使⽤ CDN
避免重定向
图⽚懒加载
减小 DOM 元素数量
减小 DOM 操做
使⽤外部 JavaScript 和 CSS
压缩 JavaScript 、 CSS 、字体、图⽚等
优化 CSS Sprite
使⽤ iconfont
字体裁剪
多域名分发划份内容到不一样域名
尽可能减小 iframe 使⽤
避免图⽚ src 为空
把样式表放在 link 中
把 JavaScript 放在⻚⾯底部
13. 负载均衡
多台服务器共同协做,不让其中某⼀台或⼏台超额⼯做,发挥服务器的最⼤做 ⽤
http 重定向负载均衡:调度者根据策略选择服务器以302响应请求,缺点只有第⼀次有 效果,后续操做维持在该服务器 dns负载均衡:解析域名时,访问多个 ip 服务器中的⼀ 个(可监控性较弱)
反向代理负载均衡:访问统⼀的服务器,由服务器进⾏调度访问实际的某个服务器,对统 ⼀的服务器要求⼤,性能受到 服务器群的数量
14. CDN
内容分发⽹络,基本思路是尽量避开互联⽹上有可能影响数据传输速度和稳 定性的瓶颈和环节,使内容传输的更快、更稳定。
15. babel原理
ES六、7 代码输⼊ -> babylon 进⾏解析 -> 获得 AST (抽象语法树 )-> plugin ⽤babel-traverse 对 AST 树进⾏遍历转译 ->获得新的 AST 树-> ⽤ babel-generator 经过 AST 树⽣成 ES5 代码
16. 谈谈你对重构的理解
⽹站重构:在不改变外部⾏为的前提下,简化结构、添加可读性,⽽在⽹站前端保持⼀致 的⾏为。也就是说是在不改变UI的状况下,对⽹站进⾏优化, 在扩展的同时保持⼀致的UI
对于传统的⽹站来讲重构一般是:
表格( table )布局改成 DIV+CSS
使⽹站前端兼容于现代浏览器(针对于不合规范的 CSS 、如对IE6有效的)
对于移动平台的优化
针对于 SEO 进⾏优化
结束篇
若是以为本文对你修炼有用,能够点个 star 。