js面试题

null 和 undefined的区别

Null表示了一个对象被定义了,但存放了空指针,转换为数值时为0
Undefined表示声明的变量未初始化,转换为数值时为NAN
typeof(null) — object typeof(undefined)—undefined

值的比较

  对象 === 字符串,对象.toString()变为字符串
  null == undefined 相等,但是和其他值比较就不再相等了
  NaN == NaN 不相等
  剩下的都是转换为数字

字符串转为数字的方法

通过parseInt(),可解析一个字符串,并返回一个整数,语法为parseInt(string,radix) String:被解析的字符串
Radix:表示要解析的数字的基数,默认是十进制,如果radix<2或radix>36,则放回NaN typeof(NaN) —
number

栈和堆的区别

栈(stack):由编译器自动分配释放,存放函数的参数值,局部变量等
堆(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由操作系统释放

startWith:参数有3个,stringObj:要搜索的字符串对象,str:搜索的字符串,position:可选,从哪个位置开始搜索。如果以position开始的字符串以搜索字符串开头,则返回true,否则返回false
Indexof:可以返回某个字符串在字符中首次出现的位置

padStart() 方法从字符串的开头用另一个字符串填充一个字符串到一定长度,并返回一个达到一定长度的结果字符串。 padEnd()
方法用另一个字符串填充一个字符串到特定长度。但是,padEnd() 方法从字符串的末尾开始填充

按需加载

当用户触发了动作时才加载对应的功能。触发的动作,是要看具体的业务场景而言,包括但不限于以下几个情况:鼠标点击,输入文字,拉动滚动条,鼠标移动,窗口大小更改等。加载的文件,可以时js,图片,css,html等

暂停死区

在代码块内,使用let,const命令声明变量之前,该变量都是不可用的。在语法上,称为暂时性死区

数组去重

1、indexof循环去重 2、es6 set:Array.from(new Set(array))
3、object键值去重。把数组的值存成Object的key值,比如Object[value1]=true。在判断另一个值的时候,如果Object[value2]存在的话,就说明该值是重复的

数组常用的方法:push,pop,shift,unshift,splice,sort,reverse,map等

mouseover和mouseenter的区别

图片懒加载和图片预加载

预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染 懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数
两种技术的本质:两者的行为是相反的,一个是提前加载,一个是延迟甚至不加载
懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力

事件委托

是:不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素dom的类型,来做出不同的响应
如ul>li,把li的事件通过ul添加

数据类型检测

(1)typeof:可以判断出string,number,boolean,undefined,symbol,function,bigint,但判
断 typeof(null) 时值为 'object'; 判断数组和对象时值均为 'object'
(2)instanceof:可以判断一个实例是否属于某种类型,也可以判断一个实例是否是其父类型或者祖先
类型的实例
(3)constructor:除了undefined和null之外,其他类型都可以通过constructor来判断。但如果声明
了一个构造函数,并且改变了它的原型执行,这种情况下constructor也不能准确判断
(4)Object.prototype.toString:判断一个对象只属于某种内置类型,但不能准确判断一个实例是否属
于某种类型
(5)Array.isArray:判断是否为数组
优先级运算符顺序
1小括号()
2一元运算符++ – !
3算数运算符先 * / 后 + -
4关系运算符> >= < <=
5相等运算符=== == == !=
6逻辑运算符先&& 后
7赋值运算符=
8逗号运算符

1、变量:存储数据的容器
2、js:运行在客户端的浏览器编程语言。

作用:网页特效,表单验证,数据交互,服务端编程等 组成部分:
ecmascript:规定了js基础语法知识。比如:变量,分枝语句,循环语句,对象等等 web apis:
dom操作文档:比如对页面元素进行移动,添加删除等操作
bom操作浏览器:比如页面弹窗,检测窗口宽度,存储数据到浏览器等等

script标签:没有defer或者async属性,浏览器会立即加载并执行对应的脚本????补充两个文档情况
有async属性,表示后续文档的加载和渲染与js脚本的加载和执行是并行进行的,即异步执行【谁快谁执行】
有defer属性,加载后续文档的过程和js脚本的加载是并行的,js脚本的执行需要等文档所有元素解析完成之后【快的要等待】 js执行顺序:按html文档流顺序执行js代码(alert和prompt他们会跳过页面渲染先被执行)

3、变量名称规则与规范

规则:
不能用关键字:有特殊含义的字符,如let var if for
只能用下划线、字母、数字、$组成,且数字不能开头,字母严格区分大小写
规范:
起名要有意义
遵守小驼峰命名法,第一个单词首字母小写,后面每个单词首字母大写

5、表达式和语句的区别

表达式可被求值,所以它可以写在赋值语句的右侧
语句不一定有值,如alert for break等就不能被用于赋值

6、循环退出:continue , break 和return

break:退出循环
continue:结束本次循环,继续下次循环
while循环,退出循环体的方法:
循环条件不成立:
while( a>0); 当 a≤0 的时候,条件 a>0不成立
使用break:如while(1){if(b>5)break;}当 b>5 的时候,程序执行 break ,跳出 while 循环体,循环体被结束
使用return:如 while(1){if(c>8) return (XXX);},当 c>8的时候,程序执行; return,退出函数返回到上级函数

7、for与while的区别:

for:明确循环次数;
while不明确循环次数

8、js作用域:

全局作用域:函数外部或者整个script有效
局部作用域:也被称为函数作用域,函数内部有效
全局变量:<script 标签和.js文件的最外层,就是全局作用域,在此申明的变量在任何地方都能被访问
局部变量:函数作用域 和 块级作用域中声明的变量
作用域:只要是代码,就至少有一个作用域。写在函数内部的叫局部作用域。在函数被执行时,会优先在当前作用域中查找变量;如果当前作用域查找不到,则会依次逐级查找父级作用域,直到全局作用域。子作用域能够访问父作用域,父级作用域无法访问子级作用域
作用域链:嵌套关系的作用域串起来形成了作用域链,作用域链本质上是底层的变量查询机制

9、对象

对象查语法如何写? 对象名.属性
对象改语法如何写:对象名.属性 =新值
对象增语法如何写 对象名.新属性名=新值
删除对象属性: delete 对象名.新属性名
对象[“属性”]方式,单引号和双引号都阔以: []语法里面的值如果不添加引号 默认会当成变量解析
For in语法中的k是一个变量,在循环的过程中依次代表对象的属性名

10、闭包

概念:有权访问另一个函数作用域中变量的函数
特点:可以重复利用变量,并且这个变量不会污染全局;这个变量可以一直保存在内存中,不会被垃圾回收机制回收
缺点:闭包较多的时候,会消耗内存,导致页面的性能下降,在ie浏览器中会导致内存泄漏 使用场景:防抖,节流,函数嵌套函数避免全局污染的时候

11、内存泄漏

Js里已经分配内存地址的对象,但是由于长时间没有释放或者没办法清除,造成长期占用内存的现象,会让内存资源大幅浪费,最终导致运行速度慢,甚至奔溃的情况。
垃圾回收机制因素:
未正确解绑事件处理程序removeEventListener
未清除定时器setTimeInterval
闭包:内函数内部应用来外部函数的变量,并且该函数在外部函数执行后仍然存在,就会导致引用的变量无法被垃圾回收
未释放资源:xmlHttpRequest发送请求时,如果没有正确处理和释放资源,可能会导致内存泄漏。确保在请求完成后正确关闭或释放资源
DOM元素应用:在js中引用了dom元素,在页面生命周期结束前没有释放这些引用。在spa中,注意在组件销毁时释放对dom元素的引用
循环引用:两个或多个对象互相引用,而且没有被垃圾回收机制检测到,就可能导致内存泄露哦。这是一种常见的情况,尤其在使用缓存或数据结构时
过度的闭包,
死循环
意外的全局变量

JS垃圾回收与V8垃圾回收
js中垃圾回收一般采用标识清除法和引用计数法
v8中垃圾回收采用分代回收:新生代,老生代和大对象

12、事件委托

addEventListener()方法,用于向指定元素添加事件句柄,它可以更简单的控制事件,语法为element.addEventListener(event, function,useCapture)
第一个参数时事件的类型(如click, mousedown)
第二个参数是事件触发后调用的函数
第三个参数是布尔值,用于描述事件是冒泡还是捕获。该参数是可选的
事件传递定义了元素事件触发的顺序,如果你将p元素插入到div元素中,用户点击p元素,在冒泡中,内部元素先被触发,然后再触发外部元素;捕获中,外部元素先被触发,再触发内部元素
如何让事件先冒泡后捕获
在dom标准事件模型中,是先捕获后冒泡。但是如果要实现先冒泡后捕获的效果,对于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓执行,直到冒泡事件被执行后再执行
addEventListener(‘click’,函数名,true/false)默认是false(事件冒泡),true(事件捕获)
好处:提高性能,减少事件的鄉定,也就减少了内存的占用。

13、基本数据类型和引用数据类型的区别?

基本数据类型:undefined, null, boolean, number, string, symbol,Bigint(ES10新增)
基本数据类型保存在栈内存当中,保存的就是一个具体的值 引用数据类型(复朵数据类型):object Function Array
保存在堆内存当中,声明一个引用类型的变量,它保存的是引用类型数据的地址
假如声明两个引用类型同时指向了一个地址的时候,修改其中一个那么另外一个也会改变

14、参数

  1. 动态参数:arguments 是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参
    1.arguments 是一个伪数组,只存在于函数中
    2.arguments 的作用是动态获取函数的实参
    3.可以通过for循环依次得到传递过来的实参

  2. 剩余参数
    1.是语法符号,置于最末两数形参之前,用于获取多余的实参
    2.借助…获取的剩余实参,是个真数组

    展开运算符(…),将一个数组进行展开,不会修改原数组

变量的数量大于单元值数量时,多余的变量将被赋值为? undefined 变量的数量小于
单元值数量时,可以通过什么剩余获取所有的值?剩余参数…获取剩余单元值,但只能置于最末位

15、箭头函数
在这里插入图片描述

箭头两数不会创建自己的this,它只会从自己的作用域链的上一层沿用this。
1. 箭头函数属于表达式函数,因此不存在函数提升
2. 箭头函数只有一个参数时可以省略圆括号()
3. 箭头函数函数体只有一行代码时可以省略花括号,并自动做为返回值被返回
4. 加括号的函数体返回对象字面量表达式
箭头函数里面没有arquments动态参数,可以使用剩余参数

16、解构

数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法。 基本语法:
1.赋值运算符=左侧的[] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量
2.变量的顺序对应数组单元值的位置依次进行赋值操作

对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法 基本语法:
1.赋值运算符二左侧的 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
2.对象属性的值将被赋值给与属性名相同的变量
3.注意解构的变量名不要和外面的变量名冲突否则报错
4.对象中找不到与变量名一致的属性时变量值为 undefined

17、原型

  1. 什么是实例成员?实例对象的属性和方法即为实例成员
  2. 什么是静态成员?构造函数的属性和方法被称为静态成员

Js 实现面向对象需要借助于谁来实现? 构造函数
构造函数存在什么问题?浪费内存

原型就是一个普通对象,它是为构造函数的实例共享属性和方法;所有实例中引用的原型都是同一个对象
使用prototype可以把方法挂在原型上,内存值保存一份
proto可以理解为指针,实例对象中的属性,指向了构造函数的原型 (prototype)

对象都会有一个属性_proto_指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype
原型对象的属性和方法,就是因为对象有 proto 原型的存在。
注意:
proto__是JS非标准属性
[prototype]和_proto_意义相同
用来表明当前实例对象指向哪个原型对象prototype
_proto_对象原型里面也有一个 constructor属性,指向创建该实例对象的构造函数
在这里插入图片描述

原型链-查找规则
1、当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
2、如果没有就查找它的原型(也就是_proto_指向的 prototype 原型对象)
3、如果还没有就查找原型对象的原型 (Object的原型对象)
4、依此类推一直找到 Object 为止(null)
_proto_对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线
回可以使用 instanceof 运算符用于检测构造西数的 prototype 属性是否出现在某个实例对象的原型链上

js是如何实现继承的?

原型链继承
借用构造函数继承
组合式继承
ES6的class类继承

18、new操作符具体做了什么?

先创建一个空对象
把空对象和构造函数通过原型链进行链接
把构造函数的this都定到新的空对象身上
根据构造函数返回的类型判断,如果是值类型,则返回对象,如果是引用类型,就要返回这个引用类型(默认函数this)

19、Js的设计原理是什么?

JS引擎 运行上下文 调用栈 事件循环 回调

20、JS中关于this指向的问题

  1. 全局对象中的this指向
    指向的是window
  2. 全局作用域或者普通两数中的this
    指向全局window
  3. this永远指向最后调用它的那个对象 在不是箭头函数的情况下
  4. new 关键词改变了this的指向
  5. apply, call,bind 可以改变this指向,不是箭头函数
  6. 箭头函数中的this 它的指向在定义的时候就已经确定了 箭头函数它没有this,看外层是否有函数,有就是外层函数的this,没有就是window
  7. 匿名函数中的this
    永远指向了window,匿名函数的执行坏境具有全局性,因此this指向window 1.函数内不存在this,沿用上一级的,过程:向外层作用域中,一层一层查找this,直到有this的定义
    2.不适用
    构造函数,原型函数,字面量对象中函数,dom事件函数
    3.适用
    需要使用上层this的地方

21、setTimeout最小执行时间是多少?

HTML5规定的内容: setTimeout最小执行时间是4ms;setInterval最小执行时间是10ms

22、es6新特性

  1. 新增块级作用域
    Iet,const 不存在变量提升
    存在暂时性死区的问题
    块级作用域的内容
    不能在同一个作用域内重复声明
  2. 新增了定义类的语法糖 (class)
  3. 新增了一种基本数据类型 (symbol)
  4. 新增了解构赋值
    从数组或者对象中取值,然后给变量赋值
  5. 新增了函数参数的默认值
  6. 给数组新增了API
  7. 对象和数组新增了扩展运算符
  8. Promise
    解决回调地狱的问题。
    自身有all,reject,resolve,race方法
    原型上有then,catch
    把异步操作队列化
    三种状态:pending初始状态,fulfilled操作成功,rejected操作失败
    状态:pending -> fulfilled;pending ->rejected 一旦发生,状态就会凝固,不会再变
    async await 同步代码做异步的操作,两者必须搭配使用
    async表明西数内有异步操作,调用两数会返回promise
    await 是组成async的表达式,结果是取决于它等待的内容,如果是promise那就是promise的结果,如果是普通函数就讲行链式调用
    await后的promise如果是reject状态,那么整个async两数都会中断,后面的代码不执行
  9. 新增了模块化 (import,export)
  10. 新增了set和map数据结构
    set就是不重复
    mapkey的类型不受限制
  11. 新增了generator
  12. 新增了箭头函数
    不能作为构造两数使用,不能用new
    箭头函数就没有原型
    箭头函数没有arguments
    箭头函数不能用call,apply,bind去改变this的执行
    this指向外层第一个函数的this

23、call,aply,bind三者有什么区别?

fun.call(thisArg, arg1, arg2, …)
thisArg:在fun 函数运行时指定的 this 值 arg1,
arg2:传递的其他参数 返回值就是西数的返回值,因为它就是调用函数
fun.apply(thisArg, [argsArray])
thisArg:在fun西数运行时指定的 this 值 argsArray:传递的值,必须包含在数组里面
返回值就是函数的返回值,因为它就是调用函数 因此apply 主要跟数组有关系,比如使用 Math.max()求数组的最大值
fun.bind (thisArg, arg1, arg2, … 主要应用场景: call 调用函数并且可以传递参数
apply经常跟数组有关系.比如借助于数学对象实现数组最大值最小值 bind 不调用函数,但是还想改变this指向.
比如改变定时器内部的this指向。

24、如何实现一个拷贝?

浅拷贝和深拷贝只针对引用类型 深拷贝就是完全拷贝一份新的对象,会在堆内存中开辟新的空问,拷贝的对象被修改后,原对象不受影响
主要针对的是引用数据类型
1.扩展运算符
2.JSON.parse (JSoN. stringify()
3.利用递归函数实现 浅拷贝:拷贝的是地址
常见方法:
1.拷贝对象:Object.assgin()/ 展开运算符 {…obj拷贝对象}
2.拷贝数组:Array.prototype.concat() 或者 […arr]

在这里插入图片描述

25、事件循环。Eventloop

Js是一个单线程的脚本语言 主线程 执行栈 任务队列 宏任务 微任务
主线程先执行同步任务,然后才去执行任务队列里的任务,如果在执行宏任务之前有微任务,那么要先执行微任务,全部执行完之后等待主线程的调用,调用完之后再去任务队列中查看是否有异步任务,这样一个循坏往复的过程就是事件循环!

macrotasks: setTimeout, setInterval, setImmediate, I/O, UI rendering
microtasks: process.nextTick, Promise, MutationObserver
宏任务:setTimeout、setInterval、Ajax、DOM事件等
微任务:promise、async/await、Object.observe等
执行顺序:同步任务->微任务->宏任务
区别:
宏任务:DOM渲染后触发,如setTimeout
微任务:DOM渲染前触发,如promise

26、ajax是什么?怎么实现的?

创建交互式网页应用的网页开发技术 在不重新加载整个网页的前提下,与服务器交换数据并更新部分内容
通过xmlHttpRequest对象向服务器发送异步请求,然后从服务器拿到数据,最后通过JS操作DOM更新页面

  1. 创建xmlHttpRequest对象 xmh
    2.通过xmh对象里的open()方法和服务器建立连接
    3.构建请求所需的数据,并通过xmh对象的send()发送给服务器
    4.通过xmh对象的onreadystatechange事件监听服务器和你的通信状态
    5.接收并处理服务器响应的数据结果
    6.把处理的数据更新到HTML页面上

27、get和post有什么区别?

1.get一般是获取数据,post一般是提交数据
2.get 参数会放在url上,所以安全性比较差,post是放在body中
3.get请求刷新服务器或退回是没有影响的,post请求退回时会重新提交数据
4.get请求时会被缓存,post请求不会被缓存
5.get请求会被保存在浏览器历史记录中,post不会
6.get请求只能进行ur1编码,post请求支持很多种

Get请求传递长度的误区

http协议从未规定get/post的请求长度限制。堆get请求参数的限制是来源于浏览器或web服务器,浏览器或web服务器限制了url的长度。不同的浏览器和web服务器,限制的最大长度不一样。ie最大长度是2083byte,chrome最大长度是8182byte

28、promise的内部原理是什么?它的优缺点是什么?

promise对象,封装了一个异步操作并且还可以获取成功或失败的结果
promise主要就是解決回调地狱的问题,之前如果异步任务比较多,同时他们之间有相互依赖的关系,就只能使用回调函数处理,这样就容易形成回调地狱,代码的可读性差,可维护性也很差
有三种状态:pending初始状态fulfilled成功状态 rejected失败状态 状态改变只会有两种情況, pending ->
fulfilled;pending ->rejected一旦发生,状态就会凝固,不会再变
首先就是我们无法取消promise,一旦创建它就会立即执行,不能中途取消 如果不设置回调,promise内部抛出的测u哦呜就无法反馈到外面
若当前处于pending状态时,无法得知目前在哪个阶段。 原理:
构造一个promise实例,实例需要传递函数的参数,这个函数有两个形参,分别都是函数类型,一个是resolve,一个是reject
promise 上还有then方法,这个方法就是来指定状态改变时的确定操作,resolve是执行第一个函数,reject是执行第二个函数

29、promise和async await的区别是什么?

都是处理异步请求的方式 promise是ES6, async await 是ES7的语法 async
await是基于promise实现的,他和promise都是非阻塞性的 优缺点:
promise是返回对象我们要用then,catch方法去处理和捕获异常,并且书写方式是链式,容易造成代码重叠,不好维护,async
await 是通过try catch进行捕获异常 sync
await最大的优点就是能让代码看起来像同步一样,只要遇到await就会立刻返回结果,然后再执行后面的操作
Promise.then()的方式返回,会出现请求还没返回,就执行了后面的操作

在这里插入图片描述

30、浏览器的存储方式有哪些?

1.cookiesH5标准前的本地存储方式( cookie 的作用:保存用户登录状态。 cookie 还可以设置 过期时间,当超过时间期限后,cookie就会自动消失。)
兼容性好,请求头自带cookie
存储量小,资源浪费,使用麻烦(封装)
cookie 数据始终在同源的 http 请求中携带(即使不需要),即 cookie在浏览器和服务器间来回传递。cookie 数据还有路径(path)的概念,可以限制 cookie 只属于某个路径下,存储的大小很小只有 4K 左右
2. localstorage 5M
H5加入的以键值对为标准的方式
操作方便,永久存储,兼容性较好
保存值的类型被限定,浏览器在隐私模式下不可读取,不能被爬虫
3. sessionstorage
当前页面关闭后就会立刻清理,会话级别的存储方式
4. indexedDB
H5标淮的存储方式,,他是以键值对进行存储,可以快速读取,适合WEB场景
Cookie、sessionStorage、localStorage 的区别

服务器端设置session,服务器返回给客户端的信息,在相应头中,带着set-cookie=‘connect.sid’
共同点:都是保存在浏览器端,并且是同源的

31、token存在sessionstorage还是localStorage?

token:验证身份的令牌,一般就是用户通过账号密码登录后,服务端把这些凭证通过加密等一系列操作后得到的字符串
1.存localStorage里,后期每次请求接口都需要把它当作一个字段传给后台
2.存cookie中,会自动发送,缺点就是不能跨域 如果存在localStorage中,容易被xSS攻击,但是如果做好了对应的措施,那么是利大于弊 如果存在cookie中会有CSRF攻击

32、token的登录流程。

客户端用账号密码请求登录 服务端收到请求后,需要去验证账号密码 验证成功之后,服务端会签发一个token,把这个token发送给客户端
客户端收到token后保存起来,可以放在cookie也可以是localstorage
客户端每次向服务端发送请求资源的时候,都需要携带这个token
服务端收到请求,接着去验证客户端里的token,验证成功才会返回客户端请求的数据

33、页面渲染的过程是怎样的?

DNS解析
建立TCP连接
发送HTTP请求
服务器处理请求
渲染页面
浏览器会获取HTML 和CSs的资源,然后把HTML解析成DOM树
再把cSS解析成CSSOM 把DOM和CSSOM合并为渲染树
布局
把渲染树的每个节点渲染到屏幕上(绘制
断开TCP连接

34、DOM树和渲染树有什么区别?

DON树是和HTML标签一一对应的,包括head和隐藏元素
渲染树是不包含head和隐藏元素

35、精灵图和base64的区别是什么?

精灵图:把多张小图整合到一张大图上,利用定位的一些属性把小图显示在页面上,当访问页面可以减少请求,提高加载速度
base54:传输8Bit宁节代码的编码方式,把原本二进制形式较为64个字符的单位,最后组成宇符串 base64是会和html
css一起下载到浏览器中,减少请求,减少跨域问题,但是一些低版本不支持,若base4体积比原图片大,不利于css的加载。

36、sVg格式了解多少?

基于xML语法格式的图像格式,可缩放矢量图,其他图像是基于像素的,SVG是属于对图像形状的描述,本质是文本文件,体积小,并且不管放大多少倍都不会失真
1.SvG可直接插入页面中,成为DOM一部分,然后用JS或CSS进行操作 <SVg
2.SVG可作为文件被引入 ‹img src=“pic.svg” />
3.SVG可以转为base64引入页面

37、了解过JWT吗?

JSON web Token 通过JSON形式作为在web应用中的令牌,可以在各方之间安全的把信息作为JSON对象传输 信息传输、授权
JWT的认证流程 前端把账号密码发送给后端的接口 后端核对账号密码成功后,把用户id等其他信息作为JWT
负载,把它和头部分别进行base64編码拼接后签名,形成一个JWT (token)。 前端每次请求时
都会把JWT放在HTTP请求头的Authorization字段内
后端检查是否存在,如果存在就验证了NT的有效性(签名是否正确,token是否过期)
验证通过后后端使用JWT中包含的用户信息进行其他的操作,并返回对应结果
简洁、包含性、因为Token是JsON加密的形式保存在客户端,所以JMT是跨语言的,原则上是任何web形式都文特。

38、HTTP协议规定的协议头和请求头有什么?

请求头信息:
Accept:浏览器告诉服务器所支持的数据类型
Host:浏览器告诉服务器我想访问服务器的哪台主机
Referer:浏览器告诉服务器我是从哪里来的(防盗链)
User-Agent:浏览器类型、版本信息
Date:浏览器告诉服务器我是什么时候访问的
Connection:连接方式cookie
x-Request-With:请求方式
响应头信息:
Location:这个就是告诉浏览器你要去找谁
server:告诉浏览器服务器的类型
content-Type:告诉浏览器返回的数据类型
refresh:控制了的定时刷新

39、说一下浏览器的缓存策略。

强缓存(本地缓存)、协商缓存 (弱缓存)
强缓:不发起请求,直接使用缓存里的内容,浏览器把JS,cSS,image 等存到内存中,下次用户访问直接从内存中取,提高性能
协缓:需要像后台发请求,通过判断来決定是否使用协商缓仔,如果请求内容没有变化,则返回304,浏览器就用缓存里的肉容
强缓存的触发:
HTTP1.0:时间戳响应标头
HTTP1.1:Cache-control响应标头
协商缓存触发:
HTTP1.0:请求头:if-modified-since 响应头:last-modified
HTTP1.1:请求头:if-none-match 响应头:Etag

40、说一下什么是“同源策略°?
http:// www.aaa.com:8080/index/vue.js
协议 子域名 主域名端口号
资源
同源策略是浏览器的核心,如果没有这个策略就会遭到网络攻击
主要指的就是协议+域名+端口号三者一致,若其中一个不一样则不是同源,会产生跨域
三个允许跨域加载资源的标签:img link script
跨域是可以发送请求,后端也会正常返回结果,只不过这个结果被浏览器拦截了!
JSONP

通过动态创建 script,再请求一个带参网址实现跨域通信。 “func({…})”

iframe 跨域:

document.domain:两个页面都通过 js 强制设置 document.domain 为基础主域,就实现了同域。
window.name :window.name + iframe跨域:通过iframe的src属性由外域转向本地域,跨域数据即由iframe的 window.name 从外域传递到本地域。
location.hash:ocation.hash + iframe 跨域:a 欲与 b 跨域相互通信,通过中间页 c 来实现。三个页面,不同域之间利用 iframe 的 location.hash 传值,相同域之间直接 js 访问来通信。 》> postMessage

CORS:

服务端设置 Access-Control-Allow-Origin 即可,前端无须设置,若要带 cookie 请求,前后端都需要设置。

代理跨域:起一个代理服务器,实现数据的转发(proxy,nginx)

ajax与jsonp的实质不同
ajax的核心是通过xmlHttpRequest获取非本页内容
jsonp的核心是动态添加script标签调用服务器提供的js脚本
jsonp只支持get请求,ajax支持get和post请求

41、防抖和节流是什么?

节流:就是指连续触发事件但是在八秒中只执行一次函数,比如可以利用节流实现 15之内 只能触发一次鼠标移动事件
防抖:如果在n秒内又触发了事件,则会重新计算函数执行时 2.节流和防抖的使用场景是?
节流:鼠标移动,页面尺寸发生变化,滚动条滚动等开销比较大的情况下 >
防抖:搜索框输入,设定每次输入完毕n秒后发送请求,如果期间还有输入,则从新计算时间 都是应对页面中频繁触发事件的优化方案
防抖:避免事件重复触发 使用场景:1.频繁和服务端交互 2.输入框的自动保存事件 节流:把频繁触发的事件减少,每隔一段时间执行
使用场景:scroll事件

function debounce(func, delay) {
  let timer = null;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}
function throttle(fn, delay){
    let valid = true;
    return function () {
        if(valid){ // 如果烟门已经打开,就继续往下
            setTimeout(()=>
                fn.apply(this, arguments);//定时器结束后执行
                valid = true;//执行完成后打开阔门
            }, delay)
            valid = false;//关闭阀门
    }
}

42、解释一下什么是json?

JSON是一种纯宇符串形式的数据,它本身不提供任何方法,适合在网络中进行传输
JSON数据存储在json文件中,也可以把JSON数据以字符串的形式保存在数据库、cookise中 JS提供了JSON.parse()
JsoN.stringify( 什么时候使用json:定义接口;序列化;生成token;配置文件package.json

43、有没有做过无感登录?

在相应其中拦截,判断token返回过期后,调用刷新token的接口
后端返回过期时间,前端判断itoken的过期时间,去调用刷新token的接口 写定时器,定时刷新token接口 流程:
登录成功后保存token 和refresh_token 在响应拦截器中对401状态码引入刷新token的api方法调用
替换保存本地新的token
4. 把错误对象里的token替换
5. 再次发送未完成的请求
6.如果refresh_token过期了,判断是否过期,过期了就清楚所有token重新登录

44、大文件上传是怎么做的?分片上传:

把需要上传的文件按照一定的规则,分割成相同大小的数据块
初始化一个分片上传任务,返回本次分片上传的唯一标识
按照一定的规则把各个数据块上传
发送完成后,服务端会判断数据上传的完整性,如果完整,那么就会把数据库合并成原始文件
断点续传: 服务端返回,从哪里开始 浏览器自己处理

页面显示白屏的原因

  1. Vue.js 文件加载失败:如果 Vue.js 文件加载失败,则页面中就不会有 Vue.js 的代码执行,导致页面内容无法显示。
  2. Vue.js 代码错误:如果 Vue.js 代码中存在语法错误或逻辑错误,则 Vue.js 可能无法正常执行,导致页面内容无法正常显示。
  3. 绑定的数据不存在:Vue.js 中,页面中的内容通常是通过数据来绑定的,如果绑定的数据不存在或无法正常获取,则页面内容也无法显示。
  4. 渲染顺序错误:Vue.js 中,通常需要在页面中指定一个元素作为 Vue 实例的挂载点,如果在 Vue 实例初始化之前就渲染了挂载点元素,则 Vue 实例无法正常挂载,导致页面内容无法显示。
  5. 其他原因:除了上述原因之外,Vue 首页白屏还可能由于其他原因造成,例如浏览器兼容性问题

46、大数据相加

const fn = (num) => {
    let arr = num.split('').reverse()
    return arr
}
let arr1 = fn(num1)
let arr2 = fn(num2)
let arr3 = []
let maxLen = arr1.length > arr2.length ? arr1.length : arr2.length
let isAdd = false // 是否需要进位
for (let i = 0; i < maxLen; i++) {
    arr3[i] = (arr1[i] || 0) * 1 + (arr2[i] || 0) * 1 + (isAdd ? 1 : 0)
    if (arr3[i] > 9) {
        isAdd = true
        arr3[i] = arr3[i] % 10
    } else {
        isAdd = false
    }
}
let str = arr3.reverse().join('')
console.log('str =', str);

TCP的三次握手和四次挥手

TCP的三次握手和四次挥手实质就是TCP通信的连接和断开。
三次握手:为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系,并建立虚连接。
四次挥手:即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。
1、三次握手
TCP协议位于传输层,作用是提供可靠的字节流服务,为了准确无误地将数据送达目的地,TCP协议采纳三次握手策略。
三次握手原理:
第1次握手:客户端发送一个带有SYN(synchronize)标志的数据包给服务端;
第2次握手:服务端接收成功后,回传一个带有SYN/ACK标志的数据包传递确认信息,表示我收到了;
第3次握手:客户端再回传一个带有ACK标志的数据包,表示我知道了,握手结束。
2、四次挥手
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务
后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP
连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
四次挥手原理:
第1次挥手:客户端发送一个FIN,用来关闭客户端到服务端的数据传送,客户端进入FIN_WAIT_1状态;
第2次挥手:服务端收到FIN后,发送一个ACK给客户端,确认序号为收到序号+1(与SYN相同,一个FIN
占用一个序号),服务端进入CLOSE_WAIT状态;
第3次挥手:服务端发送一个FIN,用来关闭服务端到客户端的数据传送,服务端进入LAST_ACK状态;
第4次挥手:客户端收到FIN后,客户端t进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为
收到序号+1,服务端进入CLOSED状态,完成四次挥手。

写出原生 Ajax
Ajax 能够在不重新加载整个页面的情况下与服务器交换数据并更新部分网页内容,实现
局部刷新,大大降低了资源的浪费,是一门用于快速创建动态网页的技术
1、创建 XMLHttpRequest 对象 var xhr = new XMLHttpRequest();
2、向服务器发送请求,使用 xmlHttpRequest 对象的 open 和 send 方法,
3、监听状态变化,执行相应回调函数

var xhr = new XMLHttpRequest(); 
xhr.open('get', 'aabb.php', true); 
xhr.send(null); 
xhr.onreadystatechange = function() { 
if(xhr.readyState==4) { 
if(xhr.status==200) { 
console.log(xhr.responseText); 
}}
}

Cookie 和 Token 的区别
Cookie

是来弥补 HTTP 无状态的问题的,Cookie可以作为一个状态保存的状态机,用来保存用户的相关登录状态,当第一次验证通过后,服务器可以通过 set-cookie 令客户端将自己的 cookie 保存起来,当下一次再发送请求的时候,直接带上 cookie 即可,而服务器检测到客户端发送的 cookie 与其保存的 cookie 值保持一致时,则直接信任该连接,不再进行验证操作。

Token

Token, 令牌,代表执行某些操作的权利的对象,简单来说,就是类似 cookie
的一种验证信息,客户端通过登录验证后,服务器会返回给客户端一个加密的token,然后当客户端再次向服务器发起连接时,带上token,服务器直接对token进行校验即可完成权限校验。
token相对cookie的优势:
1、支持跨域访问 ,将token置于请求头中,而cookie是不支持跨域访问的;
2、无状态化, 服务端无需存储token ,只需要验证token信息是否正确即可,而session需要在服务端存储,一般是通过cookie中的sessionID在服务端查找对应的session;
3、 无需绑定到一个特殊的身份验证
方案(传统的用户名密码登陆),只需要生成的token是符合我们预期设定的即可;
4、 更适用于移动端(Android,iOS,小程序等等),像这种原生平台不支持cookie;
5、 避免CSRF跨站伪造攻击;
6、 非常适用于RESTfulAPI ,这样可以轻易与各种后端(java,.net,python…)相结合,去耦合

前端如何优化网站性能
1、减少 HTTP 请求数量
2、控制资源文件加载优先级
3、利用浏览器缓存
4、CSS Sprites:国内俗称CSS精灵,这是将多张图片合并成一张图片达到减少HTTP请求的一种解决方案,可以通过CSS的background属性来访问图片内容。这种方案同时还可以减少图片总字节数。
5、合并 CSS 和 JS 文件: 现在前端有很多工程化打包工具,如:grunt、gulp、webpack等。为了减少 HTTP 请求数量,可以通过这些工具再发布前将多个CSS或者多个JS合并成一个文件。
6、采用 lazyLoad: 俗称懒加载,可以控制网页上的内容在一开始无需加载,不需要发请求,等到用户操作真正需要的时候立即加载出内容。这样就控制了网页资源一次性请求数量。
7、浏览器在加载HTML内容时,是将HTML内容从上至下依次解析,解析到link或者script标签就会加载href或者src对应链接内容,为了第一时间展示页面给用户,就需要将CSS提前加载,不要受 JS 加载影响。一般情况下都是CSS在头部,JS在底部。
8、减少重排(Reflow)
减少Reflow,如果需要在DOM操作时添加样式,尽量使用 增加class属性,而不是通过style操作样式。
9、图标使用 IconFont 替换

什么叫优雅降级和渐进增强

渐进增强(Progressive
Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。 比如一开始使用 CSS3的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览。
其实渐进增强和优雅降级并非什么新概念,只是旧的概念换了一个新的说法。在传统软件开发中,经常会提到向上兼容和向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容。
区别:优雅降级是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带

map和Object的区别

(1)意外的键:Map默认不包含任意键,只包含插入的键值;Object有一个原型、原型链的键名可能 和自己在对象上设置的键名发生冲突;
(2)键的类型:Map键的类型是任意的;Object键的类型是string和symbol;
(3)键的顺序:Map有序的,迭代的时候以其插入的顺序返回键值;Object无序的;
(4)size:Map的长度可以通过size属性获取;Object需要手动计算;
(5)迭代:Map是可迭代的;Object需要通过获取键来迭代;
(6)性能:Map在频繁增删键值对的场景下表现更好;Object在频繁添加和删除键值对的场景下未作出优化;

set 和map 的区别?

Map是键值对,Set是值的集合,键和值可以是任何的值;
Map可以通过get方法获取值,而set不能因为它只有值,set只能用has来判断,返回一个布尔值;
Set的值是唯一的可以做数组去重,Map由于没有格式限制,可以做数据存储

js常见的设计模式

(1)单例模式
(2)工厂模式
(3)构造函数模式
(4)发布订阅者模式
(5)迭代器模式
(6)代理模式

原生对象和宿主对象?

原生对象是ECMAScript规定的对象,所有内置对象都是原生对象,比如Array、 Date、RegExp等;
宿主对象是宿主环境比如浏览器规定的对象,用于完善是ECMAScript的执行环境,如Document、Location、Navigator等。

js 获取原型的方法?

Object.getPrototypeOf()
proto
constructor.prototyp

说说防抖和节流
防抖:n秒后在执行该事件,若在n秒内被重复触发,则重新计时
节流: n秒内只运行一次,若在n秒内重复触发,只有一次生效

require和import之间的区别?

1)require对应导出的方法是module.exports,import对应的方法是export default/export
2)require 是CommonJs的语法,import 是 ES6 的语法标准。
3)require是运行运行时加载模块里的所有方法(动态加载),import 是编译的时候调用(静态加
载),不管在哪里引用都会提升到代码顶部。
4)require 是CommonJs的语法,引入的是的是整个模块里面的对象,import可以按需引入模块里 面的对象
5)require 导出是值的拷贝,import 导出的是值的引用

栈和堆的区别?

1)申请方式的不同。栈由系统自动分配,而堆是人为申请开辟;
2)申请大小的不同。栈获得的空间较小,而堆获得的空间较大;
3)申请效率的不同。栈由系统自动分配,速度较快,而堆一般速度比较慢;
4)存储内容的不同。栈在函数调用时,函数调用语句的下一条可执行语句的地址第一个进栈,然后函数的各个参数进栈,其中静态变量是不入栈的。而堆一般是在头部用一个字节存放堆的大小,堆中的具体内容是人为安排;
5)底层不同。栈是连续的空间,而堆是不连续的空间。
6)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。
7)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控 制,容易产生内存泄漏;

forEach、for…in 、for…of三者的区别

1)forEach遍历数组,但不能使用break、continue和return语句
2)for…in是用来循环带有字符串key的对象的方法。实际是为循环”enumerable“(可枚举)对象而设计
的。Js基本数据类型自带的原型属性不可枚举,通过Object.defineProperty0方法指定enumeralbe为false的属性不可枚举。
3)for…in循环出的是key,for…of循环出的是value。
4)for…of数组对象都可以遍历,它是ES6中新增加的语法。一个数据结构只有部署了Symbol.iterator 属性, 才具有 iterator接口可以使用 for…of循环。for…of遍历对象需要通过和 Object.keys()

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值