js考题-进阶篇(1)
于2024-02-20 11:42:15发布
99
1. 简述下js的事件循环机制
由于js是单线程语言,同一个时间点只能执行一个任务。那如果同一个时间点,有多个任务,那到底谁先执行,谁后执行?
为了解决这个问题,js把任务分为3种,同步任务、宏任务、微任务。它们的优先级是:同步任务 > 微任务 > 宏任务
比如,此时有:2个同步任务,1个微任务,1个宏任务,js的执行流程是这样的 :
1. 从同步任务队列中获取任务,然后放到主线程执行;
2. 执行完毕后,再查看下同步任务队列是否还有任务,发现还有一个同步任务,执行步骤1;
3. 当同步任务队列没有了任务时,此时主线程会去微任务队列查看下是否有任务,发现有1个微任务,取出放到主线程执行;
4. 当微任务队列没有任务时,此时主线程会去宏任务队列查看下是否有宏任务,发现有1个宏任务,取出放到主线程执行;
5. 当所有任务队列的任务都被执行完毕时,此时已经没有任务了,则主线程会被休眠。直到下次任务队列中有任务时,则会被唤醒;
微任务:Promise.then、catch、finally、async/await
宏任务:setTimeout、setInterval、Dom事件、ajax事件
2. 网页的生成过程
1. HTML代码转化成DOM
2. CSS代码转化成CSSOM (CSS Object Model)
3. 结合DOM和CSSOM,生成一棵渲染树(渲染树包含每个节点的视觉信息。比如节点的宽、高、坐标、颜色、字体大小等。这里的节点指的是html标签)
4. 根据视觉信息,生成布局
5. 根据视觉信息,布局绘制(paint)在屏幕上
3. 当在浏览器上输入一个网址,其内部发生了什么?
当前URL是否存在缓存,若有缓存则直接使用缓存数据,否则 :
1、DNS解析 (DNS解析URL对应的IP)
2、TCP连接
3、HTTP请求
4、服务器处理请求
5、浏览器接受HTTP响应
6、页面渲染
7、TCP断开连接
4. 作用域相关的知识
作用域的优先级:声明变量 > 声明普通函数 > 参数 > 变量提升
请参考这里: http://111.230.246.226:8080/article/336
5. JS对象相关知识
对象查找属性的优先级:先在对象本身找 -> 构造函数中找 -> 对象原型中找 -> 构造函数原型中找 -> 对象上一层原型中找
请参考这里: http://111.230.246.226:8080/article/337
6. new操作符具体做了什么?
1. 创建了一个空的对象
2. 将空对象的原型,指向与构造函数的原型
3. 改变this指向
4. 构造函数的返回值做处理判断,如果返回的是基本数据类型,则忽略返回值。如果是引用数据类型,则返回
验证过程
第1步
function Fun() {
}
console.log(new Fun())
第2步
function Fun() {
}
console.log(new Fun().__proto__ === Fun.prototype) // 输出true
第3步
function Fun() {
console.log(this) // 输出window
this.name = 'lcf'
}
console.log( Fun() ) // 输出undefined
new了之后
function Fun() {
console.log(this) // 输出对象
this.name = 'lcf'
}
console.log( new Fun() ) // 输出对象
第4步
function Fun() {
this.name = 'lcf'
return 123
}
console.log( new Fun() ) // 输出对象。即使Fun返回的是123,但是这里的规则是如果Fun的return是引用类型,则按return的返回,否则忽略
7. 什么是闭包?优缺点是什么?具体可以用在什么地方?
什么是闭包?
函数b在函数a里面,并且函数b有用到函数a的变量,就叫闭包。如 :
function a() { // 函数a
var num = 10;
return function () { // 函数b
console.log(num); // 用到函数a的变量
}
}
var fun = a();
fun();
优缺点是什么?
优点:
1. 变量不会污染全局;
缺点:
1. 闭包较多的时候,会消耗内存,导致页面的性能下降,在IE浏览器中才会导致内存泄漏
具体可以用在什么地方?
防抖、节流、函数嵌套函数避免全局污染的时候
防抖和节流可以参考这篇文章: http://111.230.246.226:8080/article/261
8. 原型链
1.原型可以解决什么问题?
对象共享属性和共享方法
2.谁有原型?
函数拥有:prototype
对象拥有: __proto__
3.对象查找属性或者方法的顺序
先在对象本身找 -> 构造函数中找 -> 对象的原型找 -> 构造函数的原型找 -> 当前对象的__proto__找 -> 直到找到的值为null位置
上面的查找过程就叫原型链
原型链查找例子(查找顺序按数字大小进行)
var Person = function() {
this.name = 2;
}
Person.prototype.name = 4;
var p = new Person();
p.name = 1;
p.__proto__.name = 3;
console.log(p.name)
作者为什么要用原型来实现属性和方法的共享,可以参考这篇文章: https://blog.csdn.net/QQ408896436/article/details/79452570
9. js怎么实现继承?
请参考这篇文章: http://111.230.246.226:8080/article/338
10. call、apply、bind共同点是什么?不同点是什么?
共同点
可以改变this的指向
不同点
1. call的第二个参数开始,是一个一个参数
2. apply的第二个参数,是一个数组
3. bind返回的是一个函数
不同点1例子
var tom = {
quantity: 50, // 手机电量
charge: function (q1, q2) { // 充电宝
this.quantity = q1 + q2;
}
}
var marry = {
quantity: 0, // 手机电量
}
tom.charge.call(marry, 50, 20) // marry没有充电宝,拿tom的充电宝来用。第二个参数开始,是一个一个参数传递
console.log(marry.quantity) // 输出70
不同点2例子
var tom = {
quantity: 50,
charge: function (q1, q2) {
this.quantity = q1 + q2;
}
}
var marry = {
quantity: 0,
}
tom.charge.apply(marry, [50, 20])
console.log(marry.quantity) // 输出70
不同点3例子
var tom = {
quantity: 50,
charge: function (q1, q2) {
this.quantity = q1 + q2;
}
}
var marry = {
quantity: 0,
}
var fun = tom.charge.bind(marry);
fun(20,50)
console.log(marry.quantity)
11. 浅拷贝和深拷贝
请参考这篇文章: https://blog.csdn.net/QQ408896436/article/details/79343481
12. 前端性能优化的方法有哪些?
1.加载优化(减少http请求数),比如把多个小图片合并成雪碧图
2.合并压缩css样式表和js脚本
3.使用外链的css和js,第二次访问不会请求,从缓存处拿
4.使用CDN外链第三方库,减少项目包过大
5.服务器开启Gzip压缩
6.复杂动画效果用transform:translate 代替 position left、right...以此来尽量减少回流和重绘
7.使用事件委托
8.使用骨架屏
13. http的状态码分类
分类 | 分类描述 |
---|---|
1** | 信息,服务器收到请求,需要请求者继续执行操作 |
2** | 成功,操作被成功接收并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误,请求包含语法错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
常见的状态码
状态码 | 含义 |
---|---|
200 | 请求成 |
301 | 表示页面/资源永久性的转移到另一个位置上 |
302 | 表示页面/资源临时性的转移到另一个位置上 |
304 | 使用缓存资源 |
401 | 身份验证失败,一般是缺少token,获取token是错误的 |
403 | 服务器拒绝访问,权限不足 |
404 | 服务器无法找到被请求页面 |
500 | 服务器错误 |
502 | 网关错误 |
14. http和https区别
区别:
1、http传输数据是明文传输,不安全。https则是采用ssl加密传输数据,比http安全得多。
(https传输数据过程大概是服务器会准备2把钥匙和一个箱子,把一把钥匙和一个箱子发给用户,用户传递数据的时候,把数据放到箱子中,然后用钥匙锁上,在传递给服务器。然后服务器则用自己的钥匙把箱子打开)
2、端口不一样。http是80,https是443。
(这个只是默认端口不一样,实际上端口是可以改的)
3、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
15. http报文相关
HTTP请求:请求行、请求头、空行、请求体(只有post请求才有请求体)
HTTP响应:响应行、响应头、空行、响应体
请求行
1. 请求方式(get还是post)
2. 请求路径
3. http协议版本
请求头
1. 主机地址
2. 端口号
3. 接受的数据类型
请求体
只有post请求才有请求体,就是请求接口时传递的参数
---------------------------------------------
响应行
1. 状态码
2. 状态描述
3. http协议版本
响应头
1. 服务器名称
2. 内容类型Content-Type
3. 响应时间
响应体
接口返回的数据
更多信息请参考这篇文章: https://zhuanlan.zhihu.com/p/464834232
16. 作用域和作用域链
作用域 :全局作用域、函数作用域、块级作用域
作用域链 :查找某个属性时,先在块级作用域查找,如果没有,则在函数作用域内查找,如果还没有,则到全局作用域查找
例子
let num = 1;
function fun() {
let num = 2;
if (true) {
let num = 3;
}
console.log(num) // 2
}
fun()
17. 内存溢出和内存泄漏的区别
内存泄露:该回收的垃圾对象没有被回收,发生了内存泄露,垃圾对象越堆越多,可用内存越来越少,若可用内存无法存放新的垃圾对象,就导致内存溢出。
内存溢出:当前创建的对象的大小大于可用的内存容量大小,发生内存溢出。(比如一个只能装500毫升的水的杯子,现在装1000毫升的水,就会溢出)
内存泄露会导致内存溢出
18. 导致内存泄漏的一些场景
1、意外的全局变量泄露
2、console.log 也是全局变量
3、闭包泄露 赋值给全局变量后,对函数的引用一直存在
19. 判断一个变量是不是空对象
Reflect.ownKeys(obj).lenght === 0
该方法比较准确,如果一个对象是用Symbol作为key的时候,这种判断比JSON.stringify准确
20. 箭头函数与普通函数的区别
1. this指向的问题,箭头函数中的this指向定义时候,外层第一个普通函数的this,并且不可修改(call、apply、bind)
2. 箭头函数不能当做构造函数
3. 箭头函数没有prototype
4. 箭头函数没有arguments
21. promise相关
请参考这篇文章: http://111.230.246.226:8080/article/305
22. find和filter的区别(都不会对原数组的内容进行改变)
区别一:返回的内容不同
filter 返回的是新数组
find 返回的是具体的内容
区别二:
filter 返回整体(每一个匹配到的都返回)
find 匹配到第一个即返回
例子
var arr = [1,2,3,4,5,6,7,8,9]
var res1 = arr.filter(function(num){
return num > 5
});
console.log(res1) // 输出 [6, 7, 8, 9]
var res2 = arr.find(function(num){
return num > 5
});
console.log(res2) // 输出6
23. some和every的区别
some
如果有一项匹配则返回true
every
全部匹配才返回true
例子
var arr = [1,2,3,4,5,6,7,8,9]
var res1 = arr.some(function(num){
return num > 5
});
console.log(res1) // true
var res2 = arr.every(function(num){
return num > 5
});
console.log(res2) // false