编者按:以下面经题目来自牛客网其他作者,已注明原帖来源。
(原帖作者若不允许搬运,可私聊我进行删除处理)
答案由本人整理,不确保完全正确,有异议可评论区指出,感恩的心
在一个对象上触发某类事件,这个事件会向这个对象的的父级传播,从里到外,直至它被处理或者到达了对象层次的最顶层,即document对象。这个过程就是JavaScript的事件冒泡。
不能吧?会高频触发…
cookie、localStorage、sessionStorage、IndexDB
强缓存、协商缓存
【403】表示【服务器拒绝执行客户端的请求】
【404】表示【服务器找不到客户端所请求的资源(网页)】
【304】表示【所请求的资源并未修改(命中协商缓存)】
//时间戳版 function throttle(fn, wait) { let date = Date.now() return function () { let now = Date.now() if (now - date > wait) { fn.call(this, arguments) date = now } } } //定时器版 function throttle(fn, wait) { let timer = null return function () { if (!timer) { timer = setTimeout(() => { fn.call(this, arguments) timer = null }, wait) } } }
width和height均设为0,border设宽度,三边颜色透明,一边设置特定的color样式
// 给定一个有序(非降序)数组,可能含有重复元素,求最小的i使得A[i]等于target,不存在则返回-1 // target = 7 ,return 5 // target = 8, return -1 function binary_search(arr, item) { let low = 0 height = arr.length - 1 while (low < height) { let mid = parseInt((height + low) / 2) let guess = arr[mid] if (guess == item) { return mid } else if (guess > item) { height = mid - 1 } else { low = mid + 1 } } return -1 } let myArr = [1, 2, 3, 5, 6, 7, 7, 10] console.log(binary_search(myArr, 7)) // 最后输出的是7对应的索引下标 5 console.log(binary_search(myArr, 8)) // 找不到8 输出的是 -1
function deleteDuplicates(head) { let fir = head while (fir && fir.next) { if (fir.val == fir.next.val) { fir.next = fir.next.next } else { fir = fir.next } } return head }
function f(){} const a = f.prototype const b = Object.getPrototypeOf(f) console.log(a === b) //false
vue2生命周期:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestory、destoryedvue3生命周期:setup、onBeforeMount、onMounted、onBeforeUpdate、onUpdated、onBeforeUnmount、onUnmounted
(来源:vue源码解析之diff原理
①DOM0级事件模型:这种模型不会传播,没有事件流的概念,可以在网页中直接定义监听函数,也可以通过js属性来指定监听函数,直接在dom对象上注册事件名字。
②IE事件模型:一次事件有两个过程,事件处理阶段和事件冒泡阶段。事件处理会首先执行目标元素绑定的监听事件,然后从目标元素冒泡到document,依次检查经过的节点是否绑定事件监听函数,如果有则执行。通过attachEvent来添加监听函数,可以添加多个,会依次执行。
③DOM2级事件模型:事件有三个过程,事件捕获、事件触发和事件冒泡
css盒模型由里到外包括:content(内容)、padding(内边距)、border(边框)、margin(外边距)四个部分css盒模型有两种(box-sizing属性决定):标准模型(浏览器默认)+ IE模型标准盒子模型(content-box):元素的宽高 = content宽高
IE盒子模型(border-box):元素的宽高 = content + padding + border
①降低请求量:减少http请求、 图片懒加载、使用字体图标或css绘制代替图片
②加快请求速度:预解析DNS、使用http2.0、并行加载、CDN分发、压缩图片、gzip压缩
③缓存:http协议缓存请求、离线缓存manifest、本地缓存localStorage
(GET请求可以缓存,POST请求不能缓存。GET请求后退/刷新无害,POST后退/刷新则会致使重新提交数据)
④渲染:
JS优化(防抖、节流、事件委托、减少重排重绘)
CSS优化(提取公共样式、减少选择器嵌套、精灵图)
服务器端渲染
(客户端渲染:获取 HTML 文件,根据需要下载 JavaScript 文件,运行文件,生成 DOM,再渲染
服务端渲染:服务端返回 HTML 文件,客户端只需解析 HTML,使首屏渲染快,SEO(搜索引擎优化) 好)
CSS写在头部,JS写在底部
重绘:页面中元素发生可见性变化(比如颜色等),导致页面重新渲染的现象称为重绘。
回流(重排):页面中元素发生位置和尺寸的变化,导致部分页面回整个页面重新加载的现象称为回流(重排)。
触发重排和重绘:
• 页面首次渲染
• 浏览器窗口大小发生改变
• 元素尺寸或位置发生改变
• 元素内容变化(文字数量或图片大小等)
• 元素字体大小变化
• 添加或者删除可见的DOM元素
①进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位)
②进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。
而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
③线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC) 进行。
④但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。
锁是计算机协调多个进程或线程并发访问某一资源的机制(避免发生资源争抢)。死锁是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。解除死锁:发生死锁后,撤销进程,回收资源,分配给正在阻塞状态的进程。
Http1.x
缺陷:线程阻塞,在同一时间,同一域名的请求有一定数量限制,超过限制数目的请求会被阻塞。
Http2.0
采用二进制格式;实现多路复用(避免队头阻塞);头信息压缩,降低开销;服务器推送
js基本类型:boolean、string、number、null、undefined、symbol复杂类型?Object、Array、Function、 Date、RegExp、Map、Set……
const a = { } const b = { c:2 } a[b]= 3 console.log(a) //{ '[object Object]': 3 }
function foo() { console.log(this.bar) } var bar = "bar1" var o2 = { bar: "bar2", foo: foo } var o3 = { bar: "bar3", foo: foo } foo() //bar1 o2.foo() //bar2
①let const关键字
②扩展运算符...
③模板字符串
④promise
⑤async/await
⑥import export defaultexport
⑦class类(原型链语法糖)
⑧解构(对象or数组)
⑨箭头函数
⑩函数传参可设默认值
⑾新增数据类型 symbol set map weakset weakmap
⑿新增数组方法 from of find findIndex fill flat includes
⒀for...of 迭代器
①Map是键值对,Set是值的集合,键和值可以是任何的值;
②Map可以通过get方法获取值,set不能;
③都能通过迭代器进行for...of遍历;
④Set的值是唯一的可以做数组去重,Map由于没有格式限制,可以做数据存储;
⑤map和set都是stl中的关联容器,map以键值对的形式存储,key=value组成pair,是一组映射关系;set只有值,可以认为只有一个数据,并且set中元素不可以重复且自动排序。
①构造方式不同
//map const map = new Map() const map1 = new Map([['a',1],['b',2]]) //obj const obj = new Object() const obj1 = Object.create()②object键的类型必须是String或者Symbol、map键的类型可以是任意类型
③object中key是无序的,map中可以是有序的,按照插入的顺序返回
④object只能通过Object.key()方法或for in统计数量,map有map.size
⑤object可以通过点或中括号访问属性,map用map.get()
⑥object不具备Iterator特性,不能for of遍历,map的keys()、values()、entries()都具有迭代器
⑦object可以用JSON.stringify()进行序列化,map只能转化成JSON,不能被parse解析
⑧应用场景:object做数据存储,需要序列化时使用;map频繁更新键值对,key类型未知时使用
CSS3 硬件加速又叫做 GPU 加速,是利用 GPU 进行渲染,减少 CPU 操作的一种优化方案。CSS 中可以触发硬件加速的属性:transform、opacity、filter、will-change
function firstUniqChar(s) { for (let i = 0; i < s.length; i++) { a = s.indexOf(s[i]) b = s.indexOf(s[i], a + 1) if (b == -1) { return s[i] } } return " " } let str = 'aufsdafdsafdsag' console.log(firstUniqChar(str)) //u
导航守卫就是路由跳转过程中的一些钩子函数,就是在跳转页面的时候把路由拦下来做一些操作再放行,比如跳转前是否验证登录等。导航守卫分为三种:全局守卫、单个路由独享守卫、组件内守卫。①全局守卫:beforeEach 路由进入之前、afterEach 路由进入之后
②单个路由独享守卫:beforeEnter 路由进入之前③组件内守卫:beforeRouteEnter 路由进入之前、beforeRouteUpdate 路由更新之前、beforeRouteLeave 路由离开之前
网页默认的是一打开就会去加载所有的页面,路由懒加载就是按需加载,只加载我们点击的那个模块。原理:将路由相关的组件,不直接导入,而是改写成异步组件的写法,只有当函数被调用的时候,才去加载对应的组件内容。
追问:开发时启动或打包时间太长时如何查看打包/启动速度或时长
JavaScript 引擎创建了执行栈来管理执行上下文。可以把执行栈认为是一个存储函数调用的栈结构,遵循先进后出的原则。JavaScript 执行在单线程上,所有的代码都是排队执行。
一开始浏览器执行全局的代码时,首先创建全局的执行上下文,压入执行栈的顶部。
每当进入一个函数的执行就会创建函数的执行上下文,并且把它压入执行栈的顶部。当前函数执行完成后,当前函数的执行上下文出栈,并等待垃圾回收。
浏览器的 JS 执行引擎总是访问栈顶的执行上下文。
全局上下文只有唯一的一个,它在浏览器关闭时出栈。
Event Loop即事件循环,是指浏览器或Node的一种解决 javaScript 单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。所有任务可以分成两种,同步任务(synchronous)和 异步任务(asynchronous)。在异步任务中,又分为 宏任务(MacroTask)和 微任务(MicroTask)。EventLoop 执行机制就是先执行同步代码,然后清空微任务队列,再执行下一个宏任务。
宏任务有:<script>整体代码、setTimeout、setInterval、setImmediate、Ajax、DOM事件、I/O、UI交互事件、postMessage、MessageChannel
微任务有:process.nextTick、Object.observe、MutationObserver、Promise.then catch finally、await后
①浏览器的UI线程实时捕捉输入的内容,如果输入的不是网址或者协议不合法就使用浏览器默认的搜索引擎进行搜索(此处还会检查有没有出现非法字符,有的话会对非法字符进行转义)
②在回车之前,还会执行一次当前页面的beforeunload事件,可以让页面退出之前执行一些数据清理工作,或者,有表单没有提交的情况提示用户是否确认离开
③然后下一步浏览器进程会通过IPC把URL发送给网络进程,然后网络进程要先找本地缓存,如果有缓存,并且没有过期,就不发送请求,直接拿来解码再开始渲染流程④如果没有缓存或者缓存过期,再开始解析URL,解析出要请求的服务器 的IP地址,把请求需要的协议、域名、端口、路径等信息解析提取出来⑤根据解析出来的域名,进行DNS解析(递归+迭代),找到要请求的服务器的IP地址
⑥拿到IP地址后,三次握手建立TCP连接,https的话还需要进行TLS加密协议的握手过程⑦连接建立成功之后,浏览器会构建请求行、cookie等数据附加到请求头中,发给服务器,服务器接受请求并解析,如果没有对应的资源就404;否则检查HTTP请求头有没有包含协商缓存信息(前面命中强缓存且已过期的话就会走这个步骤),如果验证缓存没有更新,过期的缓存依然可以使用,就返回304和空响应体;如果没有缓存或者资源更新了,就读取完整请求并准备http响应,进行查询数据库等操作,返回200和查询到的资源⑧浏览器接收到响应数据之后,如果是http1.1以下则直接关闭连接,否则双方都可以根据情况选择关闭TCP连接或者保留重用,现在浏览器默认都会保持连接(keep-alive)⑨拿到资源后根据资源类型(Content-Type)决定如何处理,如果浏览器判断是下载文件,那么请求会被提交给浏览器的下载管理器,同时URL请求流程就结束了,否则网络线程会通知UI线程,然后UI线程会创建一个渲染器进程来准备渲染页面
⑩渲染
UDP(User Datagram Protocol)用户数据报协议主要特点:无连接;面向报文;没有拥塞控制;支持一对一、一对多、多对一和多对多交互通信;首部开销小,只有8字节优点:效率快,不需要建立连接及拥塞控制;连接更多的客户;首部字节少,开销小;可以进行广播缺点:无法保证消息完整、正确到达,是一个不可靠的传输协议;缺少拥塞控制容易互相竞争资源导致网络系统瘫痪适用场景:适用于对传输模型需要应用层高度自定义、允许出现丢包、需要高效率的场景、需要广播;例如视屏直播、DNS、RIP路由选择协议
http1.1默认持久连接;1.1请求头引入range头域,允许只请求某个部分,返回码206;1.1引入更多的缓存控制策略;1.1新增host字段,用来指定服务器域名;1.1新增PUT、PATCH、OPTIONS、DELETE 等请求方式http2.0为二进制协议,头信息和数据体都是二进制;2.0支持多路复用,避免队头阻塞;2.0采用头部压缩,减少请求的大小提高效率;2.0支持服务端推送
function sameEle(arr1,arr2){ let res = [] for(let i=0;i<arr1.length;i++){ let index = arr2.indexOf(arr1[i]) if(index>-1){ res.push(arr2[index]) arr2.splice(index,1) } } return res } let arr1=[1,1,1,2,2,3] let arr2=[1,1,2,4] console.log(sameEle(arr1,arr2))