JS基础
-
变量类型
JS中变量类型分为基本数据类型和复杂数据类型。
基本数据类型:Number,String,Boolean,Undefined,Null
复杂数据类型:Object
typeof和instanceof属于运算符,和+、-、*、/是一样的。
typeof取值包括:Number、String、Boolean、Undefined、Object、Function,其中
typeof null //Object
typeof {} //Object
typeof [] //Object
undefined == null //true
undefined === null //false
JS按照存储方式的不同可分为值类型和引用类型(即Object、Array、Function),而Array和Function分别继承自Object。值类型存储在栈中,引用类型在栈中存储了一个地址,这个地址指向了堆中的一个地址,这个地址存储的是实际的值。所以
var objA = {
name : 'aaa'
}
var objB = objA
objB.name = 'bbb'
console.log(objA.name) // 'bbb'
-
单线程
JS是特性之一单线程执行(注意:这与异步加载是不同的概念),为什么是单线程执行呢,这与最初的设计方向有关,假如同一个js文件,两个人都是操作,A进行DOM的增加,B进行DOM的删减,那最终的结果以谁的为准呢?为了避免出现这种复杂的场景,JS确定为单线程执行。如果说如何进行多线程呢?在HTML5中新增了Worker API,这个对象可以让目标js处理多线程,但目标js仍受原js所管理,所以其本质并未发生改变。
//当前为main.js
var workerA = new Worker('/src/a.js')
var workerB = new Worker('/src/b.js')
//a.js和b.js仍受main.js控制,单一执行。
-
原型与原型链
关于这个的解释很多了,这个推荐这篇,可以跟着文章在浏览中执行一遍,如果一遍没理解,那我建议你隔几天再来一遍。
-
作用域和闭包
ES5中只有全局作用域和函数作用域,没有块级作用域。但在ES6中多了一个let,他可以保证外层块不受内层块的影响。即内层块形成了一个块级作用域,这是let的一个特点。
ES6的箭头函数和ES5的函数有和不同?ES5的函数会绑定this和arguments,而ES6的箭头函数不会绑定这俩东西。
关于闭包的理解也多种多样,我理解是函数套函数,函数的执行结果是返回内部函数,内部函数对外部函数的引用会被加载到内部函数的作用域上,举个栗子
function A(){ //外部函数
var name = 'jack'
function B(){ //内部函数
return name //内部函数引用了外部函数变量
}
return B //返回内部函数
}
-
异步
JS的异步编程是基于事件的回调实现的。
-
事件机制
看这篇文章,比较详细的介绍了JS中事件的冒泡、捕获、传播、委托。需要注意不同浏览器的API是不同的。
-
底层执行模型
如图,在JS中,有两个队列,分别为执行栈(执行上下文:Excution Context Stack)和异步任务队列,
当浏览器解析JS时,将同步任务加到ECS中,将异步任务加到异步队列中,执行栈也即是主线程,当执行栈中的同步任务全部执行完并且为空时,就将异步队列中的任务调出,塞到执行栈中,然后依次执行,这个过程称为一个Tick,Tick对应的是函数作用域吗?有待验证。
-
节流和去抖
两者在概念上容易混淆,最终目的都是控制事件响应的频发。举个栗子来说吧,比如给onscroll加上监听事件。
window.addEventListener("scroll",function(){
console.log('scrolling...')
})
当前的效果是稍微滚动一下滚动条就会触发多次回调。去抖可以理解为去掉抖动,只有当滚动条停下的时候,再触发回调;节流可以理解为节省流量,在去抖的基础上,添加一个时间限制,这里可以是50ms,这样滚动条如果在50ms内多次触发,那只执行一次。
实现如下:
//JS函数节流
function log(){
console.log('scrolling...');
}
function throttle(fn,context,delay){
clearTimeout(fn.timerID);
fn.timerID = setTimeout(function(){
fn.call(context,value)
},delay);
}
window.addEventListener('scroll',function(e){
throttle(log,null,1000)
})
//JS函数去抖
function log(){
console.log('scrolling...');
}
function debounce(func, wait) {
var timeout;
var context = this, args = arguments;
var later = function() {
timeout = null;
func.apply(context, args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
window.addEventListener('scroll',function(e){
debounce(log,100)
})
HTML5提供了requestAnimationFrame也是解决方案之一。
-
call/apply/bind
三者的作用是一样的,都是改变this的指向,即可扩充函数执行时的作用域。比如A想喝水但没有杯子,而B有杯子,这时候A就call(呼叫)B,借一下杯子用,B.call(A)、B.apply(A)。
不同点是传参不同,call参数为不定个,apply是一个数组。
call和apply为立即执行,bind为延后执行,一般会返回一个匿名函数或者闭包。
有时需手撕bind。
-
垃圾回收机制
JS中垃圾回收机制有两种:
- 标记清除。当变量进入执行环境时,被打上标记“使用中”,这时不能被回收,离开执行环境时,被标记为“可删除”,这时可以被回收。不同浏览器的回收间隔不同。
- 引用计数。当一个变量被引用的次数为0时,即将被回收。
var a={}; var b={}; a.prop=b; b.prop=a; //这种情况a和b的引用次数都是2(循环引用),在使用引用计数回收机制的时候,就会有问题。 //需手动a=null;b=null进行清理。
-
ES6/7新标准
这里简单归纳一下重点:
字符串模板、数组扩展、箭头函数、Proxy和Reflect、Promise、class、async 函数(ES7)。
手撕Promise
class promise {
constructor() {
this.callbacks = []
}
then(success, fail) {
this.callbacks.push({
resolve: success,
reject: fail
})
return this
}
catch (fail) {
return this
}
resolve(result) {
this.actuator('resolve', result)
}
reject(result) {
this.actuator('reject', result)
}
actuator(status, result) {
let handleObj = this.callbacks.shift()
handleObj[status](result)
}
}
let p = new promise()
function f1() {
console.log('f1')
setTimeout(function() {
p.resolve('1')
}, 1000)
return p
}
function f2(result) {
console.log('f2', result)
setTimeout(function() {
p.resolve('2')
}, 1000)
}
function f3(result) {
console.log('f3', result)
setTimeout(function() {
p.resolve('3')
}, 1000)
}
function f4(result) {
console.log('f4', result)
}
// 第一种调用
f1().then(f2).then(f3).then(f4)
HTML和CSS基础
-
选择器的权重和优先级
行内样式>ID>属性选择器、class、伪类>元素名、伪元素
分别对应
1000>100>10>1
样式的优先级以“就近原则”为判定基准,但使用!important可以使其位于最高级别。
-
盒模型
-
W3C的标准盒模型。width指content部分的宽度。
-
IE的盒模型。width表示content+padding+border这三个部分的宽度。
通过改变box-sizing属性的值可以调整盒模型的width范围。
box-sizing: content-box; <!-- 是W3C盒子模型 -->
box-sizing: border-box; <!-- 是IE盒子模型 -->
利用box-sizing: content-box;写出邮箱布局布局。
-
浮动
float的元素可以向左,也可以向右,是脱离正常文档流的,直到它的外边缘碰到包含框或另一个浮动框的边框为止。
浮动最初是为了解决图片与文字的环绕问题而产生。
浮动元素会脱离文档流,所以不会占据原始空间,导致其父级元素的高度塌陷,解决办法:
1)父级也浮动
2)清楚浮动(添加空元素、添加伪类)
-
定位
position 属性值的含义:
static
元素框正常生成。块级元素生成一个矩形框,作为文档流的一部分,行内元素则会创建一个或多个行框,置于其父元素中。
relative
元素框偏移某个距离。元素仍保持其未定位前的形状,它原本所占的空间仍保留。
absolute
元素框从文档流完全删除,并相对于其包含块定位。包含块可能是文档中的另一个元素或者是初始包含块。元素原先在正常文档流中所占的空间会关闭,就好像元素原来不存在一样。元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。
fixed
元素框的表现类似于将 position 设置为 absolute,不过其包含块是视窗本身。
-
flex布局
尝试写出邮箱布局、三列布局。
-
上下左右居中
这篇整理的超级全面。
-
css3动画
要掌握animation和transition的使用,建议在浏览一些网站的时候,特别关注一些小动画,这些小动画都是css3来实现的。比如loading的转转、图片的翻转、鼠标滑过的样式变化等。
-
重绘和回流
浏览器在解析、渲染页面时会产生两个重要的动作:重绘和回流。
重绘是只改变元素的外观样式,其物理空间位置并未改变,也不会对其他元素的物理位置造成影响。
回流是元素的物理位置发生变化了,浏览器需要从此位置重新进行渲染,所以页面的DOM树层级太深或太广都会影响渲染性能。
WEB-API
-
BOM操作
浏览器对象模型(Browser Object Model)。
BOM没有相关标准,每个浏览器都有其自己对BOM的实现方式。
核心对象是window。
//常用的window对象
window.localStorage
window.sessionStorage
window.location
window.open
window.setInterval
window.setTimeout
//新版的Chrome添加大量API,有兴趣可以研究下。
-
DOM操作
文档对象模型(Document Object Model)。
核心对象是document。
看MDN的API,常用的节点增删改查要掌握。
-
事件绑定
IE方式
attachEvent(事件名称, 函数),绑定事件处理函数
detachEvent(事件名称, 函数),解除绑定
DOM方式
addEventListener(事件名称,函数, 捕获)
removeEventListener(事件名称, 函数, 捕获)
//自定义事件监听、接触类
var EventUtil = {
addHandler: function(element, type, handler) {
if (element, addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler
}
},
removeHandler: function(element, type, handler) { //类似addHandler
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
}
}
//使用
var textbox = document.getElementById('ddd');
EventUtil.addHandler(textbox, 'textInput', function(e) {
e.target.value = e.target.value.replace(/[^0-9\.]/g, '')
})
-
Ajax
异步 JavaScript 和 XML(Asynchronous Javascript And XML)。
核心对象XMLHTTPRequest。
优势:
1. 通过异步模式,提升了用户体验(局部刷新)。
2. 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用 。
3. Ajax引擎在客户端运行,承担了一部分本来由服务器承担的工作,从而减少了大用户量下的服务器负载。
劣势:
1、ajax不支持浏览器前进后退按钮。
2、存在安全问题,AJAX暴露了与服务器交互的细节。
3、对SEO支持比较弱。
常用方法和属性:
open(“method”,”URL”)
send()方法,发送具体请求
abort()方法,停止当前请求
readyState属性,请求的状态 有5个可取值0=未初始化 ,1=正在加载 2=已加载,3=交互中,4=完成
responseText属性,服务器的响应,表示为一个串 reponseXML 属性 服务器的响应,表示为XML status 服务器的HTTP状态码
常用的封装:
jquery、vue-resource、axios。
新版浏览器自带了fetch API,也属于ajax的一种,是基于Promise实现的。
-
HTTP
HTTP无状态协议,是指协议对于事务处理没有记忆能力。为了支持客户端与服务器之间的交互,我们就需要通过不同的技术为交互存储状态,而这些不同的技术就是Cookie和Session了。
常用方法:
get、post、put、delete、head、option
常见状态码:
101、200、301、302、304、400、401、403、404、500
HTTP缓存:
合理利用http缓存和html5离线存储可以有效的提高web应用的性能。
这里关于缓存。
这里关于离线存储。
-
WebSocket
ws是一种双工通信协议,是基于tcp实现,但是在握手阶段还是http协议,弥补了http协议只能客户端主动拉取数据的单一通信方式,ws可以服务端主动推送消息到客户端。
刷新浏览器链接会断开重连。
常见API:
onopen、onmessage、onerror、onclose、readyState。
对于链接超时和异常断线应添加心跳处理。
readyState:
CONNECTING:值为0,表示正在连接。
OPEN:值为1,表示连接成功,可以通信了。
CLOSING:值为2,表示连接正在关闭。
CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
-
存储
cookie、sessionStorage、localeStorage。
三者的使用场景、大小、cookie的跨域问题(服务端设置Access-Control-Allow-Credentials=true,Access-Control-Allow-Origin=xxx,不能是*,客户端withCredentials=true)。
Node
-
模块化和组件化
-
试用场景
-
常用web框架
-
爬虫
-
守护进程
开发环境
-
IDE
-
Git
-
Linux基础
-
构建工具
-
调试
浏览器相关
-
页面加载和渲染过程
-
HTTPS
-
性能优化
-
web安全
-
兼容性
算法相关
-
常用的数据结构
-
常见算法
-
常用设计模式
-
类数组结构
框架相关
-
vue双向绑定原理
-
vue何时进行依赖收集
-
vue异步更新策略
-
vuex原理
-
vue-router两种模式的实现原理
-
react基本语法
-
react和vue对比
-
虚拟DOM
项目相关
-
单点登录
-
oauth2.0