前端面试、复习
amyuan23 / fe-interview Goto Github PK
View Code? Open in Web Editor NEW前端面试、复习
前端面试、复习
JavaScript数据类型: number、string、bool、symbol、null、undefined、bigInt
原始类型的数据值都是直接保存在“栈”中的,引用类型的值是存放在“堆”中的。
栈空间都不会设置太大,主要用来存放一些原始类型的小数据。而引用类型的数据占用的空间都比较大,所以这一类数据会被存放到堆中,堆空间很大,能存放很多大的数据。
闭包的数据是存放在堆数据中的。
http 0.9
http 1.x :
http 1.1的问题: TCP 的慢启动、多条 TCP 连接竞争带宽和队头阻塞。
http 2.0
多路复用技术。多路复用是通过在协议栈中添加二进制分帧层来实现的。
二进制分帧:
首先,浏览器准备好请求数据,包括了请求行、请求头等信息,如果是 POST 方法,那么还要有请求体。
这些数据经过二进制分帧层处理之后,会被转换为一个个带有请求 ID 编号的帧,通过协议栈将这些帧发送给服务器。
服务器接收到所有帧之后,会将所有相同 ID 的帧合并为一条完整的请求信息。
然后服务器处理该条请求,并将处理的响应行、响应头和响应体分别发送至二进制分帧层。
同样,二进制分帧层会将这些响应数据转换为一个个带有请求 ID 编号的帧,经过协议栈发送给浏览器。
浏览器接收到响应帧之后,会根据 ID 编号将帧的数据提交给对应的请求。
http2.0特性:
多路复用技术能充分利用带宽,最大限度规避了 TCP 的慢启动所带来的问题,同时还实现了头部压缩、服务器推送等功能,使得页面资源的传输速度得到了大幅提升。使用 HTTP/2 能带来 20%~60% 的效率提升
TCP 的队头阻塞:
如果在数据传输的过程中,有一个数据因为网络故障或者其他原因而丢包了,那么整个 TCP 的连接就会处于暂停状态,需要等待丢失的数据包被重新传输过来。
在 TCP 传输过程中,由于单个数据包的丢失而造成的阻塞称为 TCP 上的队头阻塞。
因http2只维持一个链接,所以随着丢包率的增加,HTTP/2 的传输效率也会越来越差。当系统达到了 2% 的丢包率时,HTTP/1.1 的传输效率反而比 HTTP/2 表现得更好。
JS是单线程的。
每个渲染进程都有一个主线程,并且主线程非常繁忙,既要处理 DOM,又要计算样式,还要处理布局,同时还需要处理 JavaScript 任务以及各种输入事件。要让这么多不同类型的任务在主线程中有条不紊地执行,这就需要一个系统来统筹调度这些任务,这个统筹调度系统就是消息队列和事件循环系统。
渲染进程内部会维护多个消息队列,比如延迟执行队列和普通的消息队列。然后主线程采用一个 for 循环,不断地从这些任务队列中取出任务并执行任务。这些消息队列中的任务就是宏任务。
每个宏任务在执行时,会创建自己的微任务队列。
如果在执行微任务的过程中,产生了新的微任务,同样会将该微任务添加到微任务队列中,V8 引擎一直循环执行微任务队列中的任务,直到队列为空才算执行结束。也就是说在执行微任务过程中产生的新的微任务并不会推迟到下个宏任务中执行,而是在当前的宏任务中继续执行。
通过作用域查找变量的链条称为作用域链;JavaScript 语言的作用域链是由词法作用域决定的,而词法作用域是由代码结构来确定的。
function foo() {
var myName = " kk "
let test1 = 1
const test2 = 2
var innerBar = {
getName:function(){
console.log(test1)
return myName
},
setName:function(newName){
myName = newName
}
}
return innerBar
}
var bar = foo()
bar.setName(" gg ")
bar.getName()
console.log(bar.getName())
在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。比如外部函数是 foo,那么这些变量的集合就称为 foo 函数的闭包
闭包怎么回收?
通过垃圾回收机制
function customerPromiseAll(promises) {
return new Promise((resolve,reject)=>{
let resultCount = 0;
//计数器
let promiseLen = promises.length;
//传入的promise个数
let results = new Array(promiseLen);
//初始化数组用于存放返回结果
//按顺序执行
for (let i = 0; i < promiseLen; i++) {
let curPromise = promises[i]
if (!isPromise(curPromise)) {
curPromise = Promise.resolve(curPromise)
}
curPromise.then(value=>{
resultCount++;
results[i] = value;
//存储resolve的结果
//保证执行结果的顺序
if (resultCount === promiseLen) {
return resolve(results)
//执行完最后一个promise,则返回
}
}
, error=>{
reject(error)
//执行错误直接reject
}
)
}
}
)
}
同源策略如何保障安全?
DOM 层面:同源策略限制了来自不同源的 JavaScript 脚本对当前 DOM 对象读和写的操作。
数据层面:同源策略限制了不同源的站点读取当前站点的 Cookie、IndexDB、LocalStorage 等数据。
网络层面: 同源策略限制了通过 XMLHttpRequest 等方式将站点的数据发送给不同源的站点。(解决:CORS 跨域资源共享策略)
XSS攻击:往页面中注入恶意脚本
解决:
CSRF 攻击- 陌生链接不要随便点: 跨站请求伪造。利用服务器的漏洞和用户的登录状态来实施攻击
JavaScript 的执行机制:先编译,再执行。
当 JavaScript 执行全局代码的时候,会编译全局代码并创建全局执行上下文。
当调用一个函数的时候,函数体内的代码会被编译,并创建函数执行上下文。
而管理执行上下文的栈称为执行上下文栈,又称调用栈。
this和作用域链是两套不同的系统,它们之间基本没太多联系。
this 可以通过apply,call,bind函数显示指定。
嵌套函数中的 this 不会从外层函数中继承
箭头函数没有this, 箭头函数里的this相当于变量,继承自外层函数。
这篇文章讲的很好了:https://juejin.cn/post/6981588276356317214
JavaScript 中的原始数据类型是存储在栈空间中的,引用类型的数据是存储在堆空间中的。
栈数据的回收很简单,当一个函数执行结束之后,出调用栈的时候清理。
堆中的垃圾数据,就需要用到 JavaScript 中的垃圾回收器。
V8 中会把堆分为新生代和老生代两个区域,新生代中存放的是生存时间短的对象,老生代中存放的生存时间久的对象。
新生代的垃圾清理首先要对对象区域中的垃圾做标记;标记完成之后,就进入垃圾清理阶段,副垃圾回收器会把这些存活的对象从对象区域复制到空闲区域中,再把原来的对象区域全部清掉,然后对象区域与空闲区域进行角色翻转,如此循环往复。从而避免内存碎片。
在新生区经过两次垃圾回收依然还存活的对象,会被移动到老生区中。
老生区采用标记 - 清除(Mark-Sweep)的算法进行垃圾回收,回收之后会产生大量的内存碎片,因此还要进行标记 - 整理:让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
增量标记算法:
进行垃圾回收时,需要将正在执行的 JavaScript 脚本暂停下来,待垃圾回收完毕后再恢复脚本执行。
为了降低老生代的垃圾回收而造成的卡顿,V8 将标记过程分为一个个的子标记过程,同时让垃圾回收标记和 JavaScript 应用逻辑交替进行,直到标记阶段完成,这样就不会让用户因为垃圾回收任务而感受到页面的卡顿了。
compose的作用就是组合函数,将函数串联起来执行,前一个函数的输出值是后一个函数的输入值。
第一个函数是多元的(接受多个参数),后面的函数都是单元的(接受一个参数)。
例子:
function fn1(x){
return x + 1
}
function fn2(x){
return x * 10
}
function fn3(x){
return x - 1
}
let x = 10
let result = fn3(fn2(fn1(x))) // 109
// 使用compose
let fn = compose(fn3, fn2, fn1)
let result = fn(x)
实现compose
const compose = (...args) => x => args.reduceRight((res, cb) => cb(res), x);
实现pipe
const pipe = (...args) => x => args.reduce((res, cb) => cb(res), x)
忘记reduce的去mdn 看: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
重排:通过 JavaScript 或者 CSS 修改元素的几何位置属性,浏览器会触发重新布局,这个过程就叫重排。重排需要更新完整的渲染流水线,开销很大。
重绘:例如通过 JavaScript 更改某些元素的背景颜色,就是重绘。重绘省去了布局和分层阶段,开销比较小。
知识大串烧~
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.