前端面试题(1)

文章目录

JavaScript

1.基本数据类型和引用数据类型的区别

js中常见的基本数据类型包括 Number,String,Boolean,Null和Undifined

引用数据类型就是对象类型,比如Object,Array,Function,Data等

区别:

1.声明变量时,基本数据类型的值会存放在栈中,引用值会存储在堆中,存储在变量处的值是一个指针,指向存储对象的内存地址

2.访问的时候,因为js中是不允许直接访问保存在堆内存中的对象的,所以访问一个对象的时候,首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象的值,这就是按引用访问,而基本数据类型的值是可以直接访问到的。

3.复制变量的时候,基本数据会将元素是值得副本赋值给新变量,此后这两个变量是完全独立得,他们只是拥有独立的值,引用数据类型是把地址赋值给新变量,所以赋值后的变量和原来的变量指向的是同一片堆内存中的地址,他们任何一个发生改变都会反映到另一个变量的身上

4.参数传递的时候,ECSMScript里的所有函数的参数都是按值来传递的,基本数据类型会把变量里的值传递给参数,之后的参数和这个变量互不影响,引用数据类型的话,因为对象变量的值是这个变量在堆内存里的内存地址,所以它传递的值也就是这个内存地址,所以函数内部对这个参数进行修改也会体现在外部,因为他们都指向同一个对象。

2.js传递参数的时候如果是object的话,是按值传递还是按引用传递

这里可以参考上一题的第4点

是按值传递,不过它传递过去的是这个变量在堆空间中的内存地址,如果在函数内部把这个参数的值修改为另一个对象的内存地址,外部的变量不会受到影响,但是如果在函数内部对这片地址指向的对象进行修改的话,会影响到外部的变量,因为他们指向的是同一片内存地址。

3.Null和Undifined的区别

首先他们都属于基本数据类型,都只有一个值,并且他们都表示一个无效得值

undefined就是声明,未定义,就是一个变量最原始的状态,而非人为操作的结果,一般1.声明未赋值的值,2.访问对象上不存在的属性,3.函数定义了形参,但是没有传递值,4.使用void对表达式进行求值

null 就是空值,表示一个对象被人为重置成了空对象,而不是一个变量最原始的状态

4.为什么基本数据类型可以调用方法

1.创建实例

2.在实例上调用指定的方法

3.销毁这个实例

但是存在一个对象声明周期的问题,如果是用new创建的引用类型的实例,在执行栈流离开当前作用域的时候一直保存在内存中,但是自动创建的基本数据类型的对象只存在于一行代码的执行瞬间,然后就被立即销毁

5.应用题

var a="a"
console.log(a.__proto__ === String.prototype) //true
console.log(a.constructor === String) //true
console.log(a instanceof String); //false

为什么?

因为在读取字符串的时候会创建一个对象,但是这个对象是临时的,所以我们称它临时对象或者包装对象,所以她实际上不是一个String对象,其他原始数据类型像Number,Boolean也不是一个对象,他们都是通过包装函数来调用构造函数上的方法的

证明临时对象

a.b = "b"
console.log(a.b)  // undefined

6.概括一下构造函数创建实例的整个过程

1.内存中创建一个空对象

2.将构造函数中的this指向这个空对象

3.将构造函数中的属性以及方法添加到这个对象中

4.返回这个新对象

7.箭头函数和普通函数的区别

箭头函数使用箭头定义,普通函数使用function

箭头函数都是匿名函数,但是普通函数可以是匿名的,也可以不是

箭头函数不能用作构造函数,不能使用new

箭头函数的this指向不同,箭头函数本身不创建this,但是他在创建的时候可以捕获上下文中的this供自己使用,this一旦被捕获就不会再发生变化

箭头函数不绑定arguments,可以用reset参数…解决

结合call(),apply()方法使用对this指向没有影响,第一个参数会被忽略

箭头函数不能Generator函数,不能使用yeild关键字。

箭头函数不具有prototype原型对象

箭头函数不具有super。

箭头函数不具有new.target。

8.为什么箭头函数不能作为构造函数使用

因为箭头函数里没有this,构造函数本身是需要this的,而且箭头函数没有_ proty _属性

箭头函数 有原型函数吗?

但是箭头函数是有构造函数的,他有_ proty_但是到了他这一环就结束了,他没有自己的prototype属性。

9.函数作用域

在函数内部的作用域,属于局部作用域,在局部作用域中定义的变量只能在这个局部作用域中使用,在js中只有函数可以生成一个局部作用域,别的都不行,每一个函数都是一个局部作用域

伪全局变量

在函数内部声明变量的时候没有使用var关键字,造成的结果就是会导致生命周期变长,造成一定的负面影响,占据了全局的命名空间。

另外,在ES6引入了let和const关键字之后,除了全局作用域,函数作用域,还有一个块级作用域,在大括号内部使用let或者const关键字声明变量,变量只存在于块级作用域中,在大括号外不能访问这些变量和函数作用域相比,没有函数的限制,只要是大括号,就形成块级作用域

另外有一个词法作用域,不需要了解太多,语法作用域也叫静态作用域,在变量被创建的时候就已经确定好了,而不是执行的时候,也就是说在写好代码的时候就已经形成了,JavaScript遵循的就是词法作用域,另外相同层级的两个块级作用域之间没有办法访问到彼此块作用域中的变量。

10.生命周期和命名空间

生命周期就是指变量在内存中存活的时间,全局变量,生命周期和程序是同步的,程序不关闭,变量就一直存在

局部变量,生命周期是和函数执行同步的,函数执行结束变量就被删除了

命名空间保证了变量命名的唯一性

全局变量的命名空间是唯一的,一个页面只有一个,

局部变量的命名空间可以有很多个,一个作用域就有一个

可以用匿名函数解决命名空间的问题

需要写一大坨代码,和别人的代码配合,怎么解决命名空间的问题

把代码写在匿名函数里面。并且立即调用它

11.作用域链

在JavaScript中使用一个变量的时候,首先JavaScript引擎会在当前作用域下查找该变量,如果没有找到,就会到他的上级作用域中进行查找,以此类推直到找到这个变量或已经查找到了全局作用域,在全局作用域中如果还是没有找到就会隐式声明这个变量或者直接报错

12.javascript的执行过程

1.进行语法分析

通过浏览器通栏浏览一下整体的代码有没有少写分号,单词拼错之类的语法错误

2.Js预编译

创建AO对象或者GO对象,对其属性的操作

3.进行解释性执行

就是一行一行的读取代码 执行代码

13.js的预编译

函数的js编译过程

AO对象

指活动性对象,也叫执行期上下文,就是通常所说的作用域。这里指函数的局部作用域

预编译的过程

1.创建AO对象

2.把形参和变量声明作为对象的属性

3.把实参和形参的值统一

4.在函数体内找到函数声明,值赋为函数体

全局预解析

GO对象

全局对象

预编译过程

1.创建go对象

2.把声明的变量给到Go的属性,并且赋值为undefined

3.找到全局域中的函数声明,放到GO对象的属性上,赋值为函数体

14.过程式编程,函数式编程,命令式编程,声明式编程

过程式编程

使用一系列的流程去完成任务

函数式编程

用一系列的函数去完成任务

命令式编程

更在意过程

声明式编程

更在意结果,把细节交给底层实现

声明式编程因为隐藏了细节,所以底层实现会随着架构的优化而不断优化

声明式编程比命令式编程的抽象层次更高,但是没有绝对的谁更好,根据不同的任务选择合适的编程方式

声明式编程通常有框架或者库辅助,解决通用的业务问题就够用了。所以日常开发就够用了,所以日常开发中我们应鼓励使用声明式编程模式,命令式编程通常在实现某一个算法或者实现一个框架或库的时候需要,日常开发应该尽量避免,因为关注点分散,不易阅读,而且细节多钟爱金变量多容易出错

15.http响应状态码

100-199 信息响应

200-299 成功响应

300-399 重定向消息

400-499 客户端错误响应

500-599 服务端错误响应

常用的

200 请求成功

404 服务器找不到请求的资源

501 服务端不支持请求方式

16.回调地狱

为什么会产生回调地狱

当一个函数作为参数传入另一个参数中,并且不会立即执行,只有当满足一定条件后才会执行,这种函数称为回调函数

回调函数嵌套回调函数,会造成会带哦地狱,回调地狱是为了实现代码顺序执行而形成的一种操作,会造成代码可读性非常差,后期不好维护

如何解决回调地狱

1.Promise

两个参数 resolve和reject,异步执行成功调用resolve,失败调用reject

then方法用来接收处理成功时候的响应数据,catch方法用来接收失败时候的相应数据

promise链式编程可以保证代码的执行顺序,但是每一次在then做完处理后,一定要return一个promise对象,这样才能在下一次then中接收到数据

promise有一个最大的问题就是代码冗余

2.async/await

async在函数前表示该函数是一个异步任务,不会阻塞后面函数的执行

async函数的返回数据会自动封装为一个promise对象

17.async await底层实现用了什么技术

生成器和协程

yield

生成器就是前面带一个*的函数,这个函数可以暂时执行或恢复执行,在函数内部内部使用yield可以暂停函数的执行,切换到外部函数,其实就是携程的却换,在外部函数可以用next来恢复函数的执行

18.同步和异步的区别

同步是阻塞模式,异步是非阻塞模式

同步就是指一个进程在执行某个请求的时候,如果这个请求需要一段时间才能返回信息,那么这个进程就会一直等待,直到接收到返回信息才可以进行下一步操作。

异步就是进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态,当有消息返回的时候,系统会通知进程进行处理,这样就可以提高执行的效率。

19.js中为什么会出现深浅拷贝的问题

因为在js中数据类型分成了基本数据类型和引用数据类型两种,对于 数据类型来说,它的值直接存储在栈内存中,而对于引用类型来说,它在栈内存中仅仅存储了一个引用,而真正的数据存储在堆内存中

浅拷贝

对于常见的引用类型,对象和数组来说,他们实际上是指向内存中的某一段数据。所以,如果将一个对象/数组直接赋值给另一个对象/数组,他们指向的将是内存中的同一段数据,这就是浅拷贝
此时,如果其中一个的值改变了,另一个也会跟着改变

深拷贝

b的值不跟随着a一起变化,那就是深拷贝

a和b实际上是指向不同的内存空间,两者完全不会互相影响

20.浅拷贝会导致的问题和解决方法

比如在web开发中很常见的一种场景,数据通过接口返回,javascript通过一个数组/对象进行保存,此时如果用浅拷贝(即直接进行赋值的话),就会发现如果对保存的对象进行操作之后,原始数据里的对象也发生了变化,我们就无法再次取得原始数据了。
同时,在对变量进行初始化的时候,如果这个变量浅拷贝了其他变量,就会连带着一起初始化,导致出现问题,而且不易排查。
所以我们推荐,尽量使用深拷贝,以规避潜在难以排查的BUG。

使用深拷贝的方法

JSON.parse(JSON.stringify() )

不仅可以拷贝对象还可以拷贝数据,并且是多层拷贝,但是不能拷贝函数

ES6的运算符…

只能深拷贝第一层的数据,从第二层的对象/数组开始,就只是浅拷贝了

使用于数据的深拷贝 concat()

注意只能拷贝一层

**使用于对象 Object.assign({}, obj) **

21.typeof和instanceof检测基本数据类型的原理

typeof是利用二进制的前三位机器码进行判断,无法判断null和object

instanceof是利用原型链进行查找,如果找到就返回true,如果一直到最后一层都没有找到就返回false,无法判断null和undefined,另外不能判断字面量形式数据的数据类型

可以用object.prototype.tostring.call进行判断

22.引用数据类型用什么判断

instanceof

constructor

Object.prototype.toString.call()

23.url的组成

协议 主机 端口号 路径 查询参数 锚点

后面两个可以有可以没有

24.事件循环Event Loop

先同步再异步,微任务先执行宏任务后执行

微任务是Es6语法规定,宏任务是浏览器规定的

事件循环的整体流程

先清空call stack里面的同步代码,再执行微任务队列里面的微任务,尝试进行dom渲染,触发 Event Loop反复询问callbackQueue中是否有要执行的语句,有则放入call back继续执行

25.输入url或点击链接

生成请求发送到服务器

执行某些动作或者获取某些资源,将响应发送回客户端

处理HTML CSS和Js病构建结果页面

监控事件队列,一次处理其中一个事件

用户于页面元素进行交互

用户关闭浏览器同时应用声明周期结束

***解析URL -> 解析DNS,返回IP地址 -> 发起TCP请求,进行三次握手 -> 资源相应 -> 页面构建,包括DOM Tree节点生成,事件处理 -> 构建完毕,生命周期结束 ***

26.宏任务和微任务

宏任务是宿主触发的(Node/浏览器)
微任务是JS触发的

属于宏任务事件有如下:

  • setTimeout
  • setInterval
  • setImmediate
  • MessageChannel
  • requestAnimationFrame
  • I/O
  • UI交互事件

属于微任务事件有如下:

  • Promise.then
  • MutationObserver
  • Object.observe(已废)Proxy
  • Process.nextTick

27.定时器里的数值代表什么?

比如1s后执行,这代表什么

就是1s后把这个宏任务加入到队列里,而不是1s后去执行

28.ES5 ES6 继承的理解

ES5的继承是通过prototype或构造函数机制来实现。

ES5的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上(Parent.apply(this))。

ES6的继承机制实质上是先创建父类的实例对象this(所以必须先调用父类的super()方法),然后再用子类的构造函数修改this。具体为ES6通过class关键字定义类,里面有构造方法,类之间通过extends关键字实现继承。子类必须在constructor方法中调用super方法,否则新建实例报错。因为子类没有自己的this对象,而是继承了父类的this对象,然后对其调用。如果不调用super方法,子类得不到this对象。

注意:super关键字指代父类的实例,即父类的this对象。在子类构造函数中,调用super后,才可使用this关键字,否则报错。

29.禁止描述对象,禁止拓展的怎么操作才能访问到

obj.a

去原型链上加上这个属性

30.事件触发的过程

首先一个点击事件,事件会从最外层开始发生,到目标源,这个过程叫做事件捕获,事件再会从目标源最深的节点开始发生,一直向上传播,直到document对象,这个过程叫做事件冒泡,整个流程叫做事件流。

事件捕获

事件会从最外层开始发生,直到最具体的元素,这个过程叫做事件捕获,addEventListener有三个参数,第三个参数为true的时候为事件捕获

事件冒泡

事件再会从最内层的元素开始发生,一直向上传播,直到document对象,这个过程叫做事件冒泡,onclick有三个参数,第三个参数为true的时候为事件冒泡

阻止事件冒泡:在W3C标准里调用e.stopPropagation(),而在IE下通过设window.event.cancelBubble=true来实现
**阻止事件捕获:**event.stopImmediatePropagation (),stopImmediatePropagation包含了stopPropagation的功能

31.事件委托,事件代理的优势

  • 减少整个⻚⾯所需的内存,提升整体性能
  • 动态绑定,减少重复⼯作
  • 但是使⽤事件委托也是存在局限性:
    • focus 、 blur 这些事件没有事件冒泡机制,所以⽆法进⾏委托绑定事件
    • mousemove 、 mouseout 这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位, 对性能消耗⾼,因此也是不适合于事件委托的

32.判一个对象是数组还是函数

instanceof

constructor

Object.prototype.toString

利用原型链

Array.isArray()

33.var let const 的区别

(1)块级作用域: 块作用域由 { }包括,let和const具有块级作用域,var不存在块级作用域。块级作用域解决了ES5中的两个问题:

内层变量可能覆盖外层变量
用来计数的循环变量泄露为全局变量
(2)变量提升: var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否在会报错。

(3)给全局添加属性: 浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。

(4)重复声明: var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量。

(5)暂时性死区: 在使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。使用var声明的变量不存在暂时性死区。

(6)初始值设置: 在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。

(7)指针指向: let和const都是ES6新增的用于创建变量的语法。 let创建的变量是可以更改指针指向(可以重新赋值)。但const声明的变量是不允许改变指针的指向。
const对象的属性可以修改吗
const保证的并不是变量的值不能改动,而是变量指向的那个内存地址不能改动。对于基本类型的数据(数值、字符串、布尔值),其值就保存在变量指向的那个内存地址,因此等同于常量。
但对于引用类型的数据(主要是对象和数组)来说,变量指向数据的内存地址,保存的只是一个指针,const只能保证这个指针是固定不变的,至于它指向的数据结构是不是可变的,就完全不能控制了。

34.什么是闭包

由于在JS中,变量的作用域属于函数作用域,在函数执行后作用域就会被清理、内存也随之被收回,但是由于闭包是建立在一个函数内部的子函数,由于其可访问上级作用域的原因,即使上级函数执行完,作用域也不会随之销毁,这时的子函数—也就是闭包,便拥有了访问上级作用域中的变量的权限,即使上级函数执行完后,作用域内的值也不会被销毁。

闭包解决了什么问题

1) 一个是可以读取函数内部的变量;

2) 另一个就是让这些变量的值始终保存在内存中。

闭包有哪些应用场景

ajax请求

事件绑定的回调函数

settimeout

一个函数内部返回另一个匿名函数

闭包的this指向

window

35.防抖和节流

想象每天上班大厦底下的电梯。把电梯完成一次运送,类比为一次函数的执行和响应

假设电梯有两种运行策略 debouncethrottle,超时设定为15秒,不考虑容量限制

电梯第一个人进来后,15秒后准时运送一次,这是节流

*电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖

防抖是在n秒后执行该事件,若在n秒内被重复触发,则要重新计时

节流就是在n秒内运行一次,如果n秒内重复触发,只有一次生效

相同点

都可以通过使用setTimeout实现

目的都是降低回调的执行频率,节省计算空间

不同点

  • 函数防抖,在一段连续操作结束后,处理回调,利用clearTimeoutsetTimeout实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能

  • 函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次

应用场景

防抖在连续的事件,只需触发一次回调的场景有:

  • 搜索框搜索输入。只需用户最后一次输入完,再发送请求
  • 手机号、邮箱验证输入检测
  • 窗口大小resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。

节流在间隔一段时间执行一次回调的场景有:

  • 滚动加载,加载更多或滚到底部监听
  • 搜索框,搜索联想功能

36.0.1 + 0.2 != 0.3问题

在计算机内部存储是用二进制存储,0.1的二进制是0.00011001100的无限不循环小数,0.2是0.0011001100循环小数,在存储的时候,都会使用64位固定长度来保存,也就是双精度浮点数,最后一位进行四舍五入,这样相加之后的结果是另一个小数,不是0.3

怎么解决

  1. 用Math里的toFixed()方法,保留需要的小数点位数
  2. 先转化成整数,再相加,之后转化成小数
  3. Number.EPSILON可以用来设置“能够接受的误差范围”。比如,误差范围设为 2 的-50 次方(即 Number.EPSILON * Math.pow(2, 2)),即如果两个浮点数的差小于这个值,我们就认为这两个浮点数相等。

37.sessionStorage,localStorage与cookie的区别

1)cookie在浏览器与服务器之间来回传递
sessionStorage和localStorage不会把数据发给服务器,仅在本地保存
2)数据有效期不同
cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
sessionStorage:仅在当前浏览器窗口关闭前有效
localStorage 始终有效,长期保存
3)cookie数据还有路径的概念,可以限制cookie只属于某个路径下
存储大小也不同,cookie数据不能超过4k,sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
4)作用域不用
sessionStorage不在不同的浏览器窗口中共享
localStorage在所有同源窗口中都是共享的
cookie也是在所有同源窗口中都是共享的
WebStorage 支持事件通知机制,可以将数据更新的通知发送给监听者。Web Storage 的 api 接口使用更方便

38.cookie、session和localStorage的区别

1)cookie的内容主要包括:名字、值、过期时间、路径和域,路径与域一起构成cookie的作用范围。若不设置时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就会消失,这种生命期为浏览器会话期的cookie被称为会话cookie
2)会话cookie一般不存储在硬盘而是保存在内存里,当然这个行为并不是规范规定的。若设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再打开浏览器这些cookie仍然有效直到超过设定的过期时间。对于保存在内存里的cookie,不同的浏览器有不同的处理方式session机制。
3)当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。

39.cookie和session的区别

1)cookie数据存放在客户的浏览器上,session数据放在服务器上
2)cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session
3)session会在一定时间内保存在服务器上,当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie
4)单个cookie保存的数*据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie
5)建议将登录信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中
6)session保存在服务器,客户端不知道其中的信心;cookie保存在客户端,服务器能够知道其中的信息
7)session中保存的是对象,cookie中保存的是字符串
8)session不能区分路径,同一个用户在访问一个网站期间,所有的session在任何一个地方都可以访问到,而cookie中如果设置了路径参数,那么同一个网站中不同路径下的cookie互相是访问不到的

40.web Storage和cookie的区别

1)Web Storage的概念和cookie相似,区别是它是为了更大容量存储设计的,cookie的大小是受限的,并且每次请求一个新的页面的时候cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可跨域调用
2)web storage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookie,getCookie
3)但是cookie也是不可或缺的,cookie的作用是与服务器进行交互,作为http规范的一部分而存在的,而web Storage仅仅是为了在本地“存储”数据而生
sessionStorage、localStorage、cookie都是在浏览器端存储的数据,其中sessionStorage的概念很特别,引入了一个“浏览器窗口”的概念,sessionStorage是在同源的同窗口中,始终存在的数据,也就是说只要这个浏览器窗口没有关闭,即使刷新页面或进入同源另一个页面,数据仍然存在,关闭窗口后,sessionStorage就会被销毁,同时“独立”打开的不同窗口,即使是同一页面,sessionStorage对象也是不同的
4)Web Storage的好处
减少网络流量:一旦数据保存在本地之后,就可以避免再向服务器请求数据,因此减少不必要的数据请求,减少数据在浏览器和服务器间不必要的来回传递
快速显示数据:性能好,从本地读数据比通过网络从服务器上获得数据快得多,本地数据可以及时获得,再加上网页本身也可以有缓存,因此整个页面和数据都在本地的话,可以立即显示
临时存储:很多时候数据只需要在用户浏览一组页面期间使用,关闭窗口后数据就可以丢弃了,这种情况使用sessionStorage非常方便

41.浏览器本地存储与服务器端存储的区别

1)数据既可以在浏览器本地存储,也可以在服务器端存储
2)浏览器可以保存一些数据,需要的时候直接从本地存取,sessionStorage、localStorage和cookie都是由浏览器存储在本地的数据
3)服务器端也可以保存所有用户的所有数据,但需要的时候浏览器要向服务器请求数据
4)服务器端可以保存用户的持久数据,如数据库和云存储将用户的大量数据保存在服务器端 ,服务器端也可以保存用户的临时会话数据,服务器端的session机制,如jsp的session对象,数据保存在服务器上
5)服务器和浏览器之间仅需传递session id即可,服务器根据session id找到对应用户的session对象,会话数据仅在一段时间内有效,这个时间就是server端设置的session有效期
6)服务器端保存所有的用户的数据,所以服务器端的开销较大,而浏览器端保存则把不同用户需要的数据分别保存在用户各自的浏览器中,浏览器端一般只用来存储小数据,而非服务可以存储大数据或小数据服务器存储数据安全一些,浏览器只适合存储一般数据

42.sessionStorage、localStorage和cookie的区别

1)相同点是都是保存在浏览器端、且同源的
2)cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下
3)存储大小限制也不同,cookie数据不能超过4K,同时因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
4)数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
5)作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的
6)web Storage支持事件通知机制,可以将数据更新的通知发送给监听者
7)web Storage的api接口使用更方便

43.sessionStorage与页面js数据对象的区别

1)页面中一般的js对象的生存期仅在当前页面有效,因此刷新页面或转到另一页面这样的重新加载页面的情况,数据就不存在了
2)sessionStorage只要同源的同窗口中,刷新页面或进入同源的不同页面,数据始终存在,也就是说只要浏览器不关闭,数据仍然存在

44.数组的常用方法

1.不改变原数组的方法 : 如 shift()、unshift()、pop()等

push(),reverse(),sort(),splice(start,length,item)

2.改变原数组的方法: 如 reduce()、filter()、every()等

findIndex() forEach join() includes() map()

45.请求拦截器和响应拦截器

请求拦截器就是在请求发送前进行一些操作,比如在请求体里加上token,添加统一的cookie,请求体加验证,设置请求头等

响应拦截器是在请求得到响应之后,对响应体进行一些处理,通常是对数据进行统一的处理,也常用来判断登录失效等

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ICkL5vda-1672707051949)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\1672362531901.png)]

46.移动端的适配问题

方案一:百分比设置(不推荐)
因为不同属性百分比值,相对的可能是不同的参照物,所以百分比很难统一
在移动端适配中很少使用
方案二:rem+动态html的font-size
rem的单位是相对于html元素的font-size来设置的,如果我们需要在不同的屏幕下有不同的尺寸,可以动态的修改html的font-size值
媒体查询、js动态计算
使用lib-flexible
npm i -S amfe-flexible
使用vscode插件:px to rem 插件
方案三:vw
方案四:flex弹性布局

47.flex:1的原理

flex:1即为flex-grow:1,经常用作自适应布局,将父容器的display:flex,侧边栏大小固定后,将内容区flex:1,内容区则会自动放大占满剩余空间。

flex属性 是 flex-grow、flex-shrink、flex-basis三个属性的缩写。
flex-grow:1 放大比例(默认为0,值为1时,全屏)
flex-shrink:1 缩小比例(默认为1,空间不足,将缩小)
flex-basis:1 定义在分配多余空间之前,项目占据的主轴空间(main size),浏览器根据此属性计算主轴是否有多余空间。相当于设置初始值

48.如何设置flex左边固定右边自适应

父:display: flex;
左:width:200px;
右:flex: 1; width:100%

49.回流和重绘

什么是回流

当渲染树(Render Tree)中的部分(或全部)元素的尺寸、结构、显示隐藏等发生改变时,浏览器重新渲染的过程称为回流。

什么是重绘

当页面中元素样式的改变并不影响它在文档流中的位置时,也就是说布局没有发生改变时(比如只是改变元素的颜色)。

回流一定引起重绘,重绘不一定引起回流

回流需要更新渲染树,性能花销非常大,它们的代价是高昂的,会破坏用户体验,并且让 UI 展示非常迟缓,我们需要尽可能的减少触发重排的次数。 回流的性能花销跟渲染树有多少节点需要重新构建有直接关系,所以我们应该尽量以局部布局的形式组织 DOM 结构,尽可能小的影响重排的范围,而不是像全局范围的示例代码一样一溜的堆砌标签,因为随便一个元素触发重排都会导致全局范围的重排。

引起回流和重绘的操作

1.引起回流的操作

  1. 添加或者删除可见的 DOM 元素;
  2. 元素尺寸改变——边距、填充、边框、宽度和高度;
  3. 浏览器窗口尺寸改变——resize 事件发生时
  4. 计算 offsetWidth 和 offsetHeight 属性

2.引起重绘属性和方法

  • width
  • height
  • margin
  • padding
  • display
  • border
  • position
  • overflow
  • clientWidth
  • clientHeight
  • clientTop
  • clientLeft

50.浏览器的渲染过程

解析 HTML Source,生成 DOM 树。

解析 CSS,生成 CSSOM 树。

将 DOM 树和 CSSOM 树结合,去除不可见元素(很重要),生成渲染树( Render Tree )。

Layout (布局):根据生成的渲染树,进行布局( Layout ),得到节点的几何信息(宽度、高度和位置等)。

Painting (重绘):根据渲染树以及回流得到的几何信息,将 Render Tree 的每个像素渲染到屏幕上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值