Open Aaaaash opened 6 years ago
全称HyperText Transfer Protocol,超文本传输协议
是一个客户端和服务器端请求和应答的标准(TCP),属于应用层的通信协议
方法(GET,POST,PUT,DELETE等)
URI(统一资源标识符)
URI表示资源是什么,URL表示资源的位置
HTTP协议版本
请求头部字段
包含Host,Connection,Content-type,Content-length等
内容实体
状态码
状态码原因短语
响应头部
包含Date,Content-type,Content-length等
内容主体
HTML字符串,JSON及XML数据等
GET
主要用于获取资源 使用 GET 方法,浏览器会把 HTTP Header 和 Data 一并发送出去,服务器响应 200(OK)并返回数据
主要用于获取资源
使用 GET 方法,浏览器会把 HTTP Header 和 Data 一并发送出去,服务器响应 200(OK)并返回数据
POST
主要目的是传输存储在内容实体中的数据 使用 POST 方法,浏览器先发送 Header,服务器响应 100(Continue)之后,浏览器再发送 Data,最后服务器响应 200(OK)并返回数据
主要目的是传输存储在内容实体中的数据
使用 POST 方法,浏览器先发送 Header,服务器响应 100(Continue)之后,浏览器再发送 Data,最后服务器响应 200(OK)并返回数据
HEAD
获取报文首部 不返回报文实体主体部分 主要用于确认 URL 的有效性以及资源更新的日期时间等
获取报文首部
不返回报文实体主体部分
主要用于确认 URL 的有效性以及资源更新的日期时间等
PUT
上传文件,不带验证机制
DELETE
删除文件,同样不带验证机制
OPTIONS
查询指定的 URL 能够支持的方法
服务器返回的 响应报文 中第一行为状态行,包含了状态码以及原因短语,用来告知客户端请求的结果。
表示接受的请求正在处理
重定向
客户端错误
服务器错误
单线程,因为作为浏览器的脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM.如果是多线程,一个线程添加了一个DOM节点,另一个线程删除了DOM节点,浏览器无法判断以哪个线程为主
通过WebWorker标准可以简单模拟多线程操作,但子线程完全受主线程控制,且无法操作DOM,本质上还是单线程
单线程同步的情况下一些耗时较长的任务将会导致页面渲染阻塞甚至卡死,浏览器是多线程的,因此浏览器为这些耗时较长的任务比如HTTP,定时器以及事件监听等单独开一个线程,由于JavaScript单线程的特性,所有任务会形成一个任务队列等待被执行,所以异步线程通过回调函数将执行完毕的异步任务放到JavaScript主线程的任务队列里
回调函数
JavaScript主线程会一直循环查找任务队列里是否还有其他任务
function fn2(){ //dosomething... } function fn1() { fn2() // dosomething... } function foo(){ fn1(); } foo();
比如这段代码,函数foo在执行时,主线程发现它还需要执行函数fn1,就把它推入一个栈中,执行到fn1时又发现它需要先执行fn2,于是又将fn1推入栈中,等到fn2执行结束,继续执行fn1,fn1执行结束将继续执行foo,待所有函数执行完成,主线程会让这些函数出栈,此时说明一个任务已经执行完毕,主线程会从下一个任务队列(callback equeue)中寻找下一个任务推入栈中,这个过程就叫做EventLoop
foo
fn1
EventLoop
扑街
var a = { value: 'aaa', say: function(){ console.log(this.vlaue); } } var b = { value: 'bbb', say: function() { console.log(this.value); } } a.say = b.say; a.say(); // 输出结果是什么
输出字符串aaa,因为函数中this的指向始终是运行时调用它的对象
aaa
将请求包装为一个Promise数组,使用Promise.all执行,之后调用.then即可
高阶组件可以将多个组件中逻辑相同的部分抽离出来,由一个函数包装后形成一个新的组件,并且不影响原组件
class A extends PureComponent { componentWillMount() { console.log(this.props.name); } render(){ return <div>I am {this.props.name}</div> } } class B extends PureComponent { componentWillMount() { console.log(this.props.name); } render(){ return <div>I am {this.props.name}</div> } } function HighOrderLog(Component) { class Com extends PureComponent { componentWillMount() { console.log(this.props.name); } return <Component name={this.props.name} /> } return Com; }
异步,因为每次调用setState之后,React内部不光要更新state,还要进行一系列比如diff算法来决定下一次render,setState多次调用会造成一定程度上性能的损耗,所以React会将多个setState先合并再执行,这样一来避免了不必要的性能损失
拿到新的state有两种方法
分两种情况
因为PureComponent实现了shouldComponentUpdate方法,收到新的props后会做一次浅对比,既仅对比引用是否相同,shouldComponentUpdate方法返回布尔值,将决定组件是否进行重渲染
shouldComponentUpdate
Redux是单Store的思想,通过view->action->reducer->view的单向数据流管理页面状态
getState
dispatch
subscribe
不冲突,业务层面上可以将React的state作为内部状态,既不依赖父组件或外部环境的组件可以使用state,而一些后端返回的数据,可能需要在多个组件中共享的,则可以作为全局的状态存放在redux的state中
applyMIddleware源码解读
简单来讲就是指一个算法解决相应问题其代码执行基本语句需要的次数
算法中某个特定步骤的执行次数/对于总执行时间的估算成本,随着「问题规模」的增大时,增长的形式。
决定算法复杂度的两个重要因素是
function swap(arr, i, j) { const tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } const arrays = [21,454,6578,784534,443565,87978,4567]; function bubbleSort(arr) { const length = arr.length; for (let i = 0; i < length; i += 1) { for (let j = 0; j < length - 1; j += 1) { if (arr[j] > arr[j + 1]) { swap(arr, j, j + 1); } } } } bubbleSort(arrays); // [21, 454, 4567, 6578, 87978, 443565, 784534]
冒泡排序的策略是依次循环比较两个相邻的项,如果第一个比第二个大,则交换他们的位置,较小的项会逐渐向上移动到正确的位置
由于无论数组是否已经排序,都会对每一项进行双重的循环遍历,所以冒泡排序的时间复杂度是O(n²)
const arrays = [21,454,6578,784534,443565,87978,4567]; function insertionSort(arr) { const length = arr.length; for (let i = 1; i < length; i += 1) { for (let j = i - 1; j >= 0; j -= 1) { if (arr[j] > arr[j + 1]) { swap(arr, j, j + 1); } } } } insertionSort(arrays); // [21, 454, 4567, 6578, 87978, 443565, 784534]
插入排序的策略是,将数组分为两个部分, 假设原第一项是已经排好序的一个数组,那么用其余数组项依次与这个已经排好序的数组对比,小的交换位置,直到其余数组为空,排序结束
这段代码中,外循环从i = 1开始,即表示不论第一项多大,它被看做一个已经排好序的数组,从原数组第二项开始遍历,由于第一轮循环,有序数组只有一项,所以直接与第二项对比后交换位置,依次类推
插入排序是不稳定的排序,最好的情况下时间复杂度为O(n),最坏情况下为O(n²)
将[123, [2,32,445,[32,54,4]]]转为[123,2,32,445,32,54,4]
[123, [2,32,445,[32,54,4]]]
[123,2,32,445,32,54,4]
使用isArray方法判断是否为数组,递归调用即可
const arrays = [123, [2, 32, 445, [32, 54, 4]]]; function flatten(arr) { return arr.reduce((pre, cur) => { return pre.concat(Array.isArray(cur) ? flatten(cur) : cur); },[]) } flatten(arrays); // [123, 2, 32, 445, 32, 54, 4]
function reversalBST(root) { if (root === null) return null; const temp = root.left; root.left = root.right; root.right = temp; temp(root.left); temp(root.right); }
操作系统
进程和线程的区别
HTTP
HTTP是什么
是一个客户端和服务器端请求和应答的标准(TCP),属于应用层的通信协议
请求报文
方法(GET,POST,PUT,DELETE等)
URI(统一资源标识符)
HTTP协议版本
请求头部字段
内容实体
响应报文
HTTP协议版本
状态码
状态码原因短语
响应头部
内容主体
HTTP方法
GET
POST
HEAD
PUT
DELETE
OPTIONS
HTTP状态码
1XX
表示接受的请求正在处理
2XX
3XX
重定向
4XX
客户端错误
5XX
服务器错误
JavaScript
JavaScript是单线程还是多线程
单线程,因为作为浏览器的脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM.如果是多线程,一个线程添加了一个DOM节点,另一个线程删除了DOM节点,浏览器无法判断以哪个线程为主
通过WebWorker标准可以简单模拟多线程操作,但子线程完全受主线程控制,且无法操作DOM,本质上还是单线程
为什么单线程的JavaScript可以实现异步
单线程同步的情况下一些耗时较长的任务将会导致页面渲染阻塞甚至卡死,浏览器是多线程的,因此浏览器为这些耗时较长的任务比如HTTP,定时器以及事件监听等单独开一个线程,由于JavaScript单线程的特性,所有任务会形成一个任务队列等待被执行,所以异步线程通过
回调函数
将执行完毕的异步任务放到JavaScript主线程的任务队列里EventLoop
JavaScript主线程会一直循环查找任务队列里是否还有其他任务
比如这段代码,函数
foo
在执行时,主线程发现它还需要执行函数fn1
,就把它推入一个栈中,执行到fn1时又发现它需要先执行fn2,于是又将fn1推入栈中,等到fn2执行结束,继续执行fn1,fn1执行结束将继续执行foo,待所有函数执行完成,主线程会让这些函数出栈,此时说明一个任务已经执行完毕,主线程会从下一个任务队列(callback equeue)中寻找下一个任务推入栈中,这个过程就叫做EventLoop
用C语言实现一个事件循环
以下代码输入结果是什么,为什么?
输出字符串
aaa
,因为函数中this的指向始终是运行时调用它的对象多个异步请求,如何使所有请求结束后才执行下一步
将请求包装为一个Promise数组,使用Promise.all执行,之后调用.then即可
React
React生命周期函数有哪些
React有几种组件
高阶组件具体使用场景是什么,解决了什么问题
高阶组件可以将多个组件中逻辑相同的部分抽离出来,由一个函数包装后形成一个新的组件,并且不影响原组件
setState是同步还是异步, 为什么,调用后怎么拿到新的state
异步,因为每次调用setState之后,React内部不光要更新state,还要进行一系列比如diff算法来决定下一次render,setState多次调用会造成一定程度上性能的损耗,所以React会将多个setState先合并再执行,这样一来避免了不必要的性能损失
拿到新的state有两种方法
父组件更新state后,子组件会不会rerender
分两种情况
为什么PureComponent不会引起子组件重渲染
因为PureComponent实现了
shouldComponentUpdate
方法,收到新的props后会做一次浅对比,既仅对比引用是否相同,shouldComponentUpdate方法返回布尔值,将决定组件是否进行重渲染谈谈对Redux的理解
Redux是单Store的思想,通过view->action->reducer->view的单向数据流管理页面状态
getState
,dispatch
,subscribe
等方法的对象,它接受reducer作为参数Redux的State与React组件本身的State是否冲突
不冲突,业务层面上可以将React的state作为内部状态,既不依赖父组件或外部环境的组件可以使用state,而一些后端返回的数据,可能需要在多个组件中共享的,则可以作为全局的状态存放在redux的state中
Redux的中间件机制如何实现的
applyMIddleware源码解读
算法
算法的时间复杂度是什么意思
简单来讲就是指一个算法解决相应问题其代码执行基本语句需要的次数
决定算法复杂度的两个重要因素是
实现冒泡排序,并说明其时间复杂度
冒泡排序的策略是依次循环比较两个相邻的项,如果第一个比第二个大,则交换他们的位置,较小的项会逐渐向上移动到正确的位置
由于无论数组是否已经排序,都会对每一项进行双重的循环遍历,所以冒泡排序的时间复杂度是O(n²)
实现插入排序,并说明其时间复杂度
插入排序的策略是,将数组分为两个部分, 假设原第一项是已经排好序的一个数组,那么用其余数组项依次与这个已经排好序的数组对比,小的交换位置,直到其余数组为空,排序结束
这段代码中,外循环从i = 1开始,即表示不论第一项多大,它被看做一个已经排好序的数组,从原数组第二项开始遍历,由于第一轮循环,有序数组只有一项,所以直接与第二项对比后交换位置,依次类推
插入排序是不稳定的排序,最好的情况下时间复杂度为O(n),最坏情况下为O(n²)
数组扁平化
将
[123, [2,32,445,[32,54,4]]]
转为[123,2,32,445,32,54,4]
使用isArray方法判断是否为数组,递归调用即可
翻转二叉树