面试自我总结

165 阅读40分钟

html

img标签的title和alt

title是鼠标放在上面的显示文字,对图片的描述和进一步说明; alt是图片加载失败时,显示在网页上的替代文字,有利于SEO优化;

href、src、url的区别

href:网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接,用于超链接; src:外部资源所在位置,指向的内容将会嵌入到文档中当前标签所在位置,在请求src资源时会将其指向的资源下载并应用到文档内; url:统一资源定位符,互联网上的每个文件都有一个唯一的url,它包含的信息指出文件的位置以及浏览器应该怎么去处理它;

session、cookie、localStorage、token(h5缓存机制)

cookie:cookie在浏览器和服务器之间来回传递,有路径(path)概念,存储不能超过4k,即使关闭窗口或者浏览器,cookie过期之前一直有效,在所有同源窗口中都是共享的。cookie数据是存放在客户的浏览器上,cookie不是很安全,别人可以分析放在本地的cookie并进行cookie欺骗; session:session数据放在服务器上,浏览器对其没有限制,会在一定时间内保存在服务器上。当访问增多,会比较占用服务器的性能;localStorage和sessionStorage不会自动的把数据发给服务端,尽在本地保存,最大存储在5M左右; localStorage:数据始终有效,在所有同源窗口中都是共享的,永久存储; sessionStorage:仅在当前浏览器窗口关闭前有效,不可持久保持,不在不同的浏览器窗口中共享,即使是同一个页面; token:就是令牌,是一个字符串,主要是用于客户端身份认证,通常登录成功后,服务的返回token,客户端把token值保存下来,后续请求其他接口时,需要在请求中携带这个token值,只有服务端对token校验通过后,才允许访问;

token放在cookie里面有被窃取的可能,解决:设置令牌放在cookie的时间,用户退出认证服务时删除cookie的令牌信息,md5加密;

公钥和私钥

对称加密:公钥加密,私钥解密

websocket

实现了客户端与服务的双向通信,把三次握手简化成一次握手就可以快速长久有效的保持连接,只建立一次连接,那么这个连接就不会断,服务端如果有数据的话,会自动返回数据给客户端。 应用:消息推送、聊天、客服等。 http获取数据时,需要不断的问服务端是否有我要的数据,如果有数据就返回数据,没有就过一段时间再次询问服务端是否有我需要的数据,是无状态的,健忘,上一次的请求和这次的请求没什么联系,需要引用cookie才能解决,websocket是一次长连接,就不要一次次加入cookie,方便很多。

template和jsx+js的区别

template:模板语法(html的扩展),主要用于快速构建页面,不方便写入较复杂的逻辑处理,使用上更局限于vue本身的指令api,无法做到编码随心所欲,双大括号,大量的内置指令简化开发,学习成本低,组件作用域css,灵活性低; jsx:js的语法扩展,单大括号,灵活性高,更偏重逻辑处理,拥有js完全编程能力,一切可以变量化,更细控制交互细节; js:一种脚本语言,浏览器可以识别; jsx:即js xml,webpack把jsx转换为浏览器能识别的js,浏览器才能正常使用,jsx会自动触发编辑器以jsx模式解析当前文件,所以不会出错,就是在js里面写xml语法,使组件的结构和组件之间的关系看上去更清晰;

innerHtml和document.write的区别

document.write是重绘整个页面 innerHTML是重绘一部分

iframe有哪些缺点

iframe会阻塞主页面的Onload事件,搜索引擎的检索程序无法解读这种页面,不利于SEO; iframe和主页面共享连接池,而浏览器对相同域的链接有限制,所以会影响页面的并行加载

ssr、ssl、ssh、xss、csrf、seo

ssr 服务端渲染; ssl http升级到https 中间会通过ssl协议加密; ssh 密钥; xss 跨站脚本攻击; CSRF 跨站请求伪造; SEO 搜索引擎;

css

行内元素和块级元素

行内元素:不会自动换行,没有宽和高,设置margin和padding左右有效,上下撑大空间但是不会有边距效果,有a、b、br、span、i、label; 块级元素:又宽高,独占一行,写完后自动换行,有div、p、h1-h6、form、ul、li、ol、dl、dt、dd; 行内块元素:img、input、td; display:inline;转换为行内元素; display:block;转换为块级元素; display:inline-block;转换为行内块元素;

回流和重绘的区别

回流:当渲染时一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建; 重绘:当渲染时一些元素需要更新属性,而这些属性只是影响元素的外观风格,而不会影响布局,产生重绘; 回流会引起重绘,但重绘不一定会引起回流; 引起回流:页面首次渲染;元素字体大小变化font-size;元素内容变化(文字数量、图片大小);元素尺寸或者位置发生改变(边距、宽高、边框等);激活伪类(:hover);添加删除可见的dom元素;查询某些属性或者调用某些方法; 减少重绘回流:避免使用table布局;避免在css中使用js表达式;避免设置多层内联样式;用display:none;

css3新特性

边框:border-radius、box-shadow、border-image; 背景:background-image、background-clip、background-oigin、background-size、background-break; 文字效果:word-wrap、text-shadow、text-overflow、text-decoration; 动画:transition、transfrom、animation; 渐变:linear-gradient、radial-gradient; font-face:定义自己的字体; 属性选择器:E[att^=value]、E[att$=value]、E[att*=value]; 伪类选择器::first-child、:last-child、:root、:not、:empty; 媒体查询 多栏布局 @media screen and (width:800px) {…}; @keyfrom;

h5新增的元素

canvas绘画元素 音频(audio)和视频(video) 对本地离线储存的更好支持localstorage 和 sessionstorage 缓存方式 特殊内容元素:article、footer、header、nav、section 新增表单控件:date、time、email、url、search、calender 语义化更好的内容标签(header footer nav aside article section)

transition和animation的区别

它们大部分属性相同,都是随时间改变元素的属性值。 transition:需要触发一个事件才能改变属性,规定动画的名字、规定完成过渡效果需要多少秒或毫秒、规定速度效果、定义过渡效果何时开始; animation:不需要触发任何事件的情况下才会随时间改变属性值,指定要绑定到选择器的关键帧的名称;

移动端1像素边框问题怎么解决

transform:scale(0.5); 利用阴影,优点是没有圆角问题,缺点是颜色不好控制:-webkit-box-shadow:0 1px 1px -1px rgba(0,0,0,0.5); 利用白色背景障眼法:linear-gradient(0,#fff,#000); 媒体查询: .border { border: 1px solid #999 } @media screen and (-webkit-min-device-pixel-ratio: 2) { .border { border: 0.5px solid #999 } } @media screen and (-webkit-min-device-pixel-ratio: 3) { .border { border: 0.333333px solid #999 } }

css布局

float布局; flex布局; grid布局:功能强大。

flex设置1是什么意思

可以平均分配空间。

  • 第一个参数表示: flex-grow 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大
  • 第二个参数表示: flex-shrink 定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
  • 第三个参数表示: flex-basis****给上面两个属性分配多余空间之前, 计算项目是否有多余空间, 默认值为 auto, 即项目本身的大小

flex左边固定右边自适应

.left{with:固定} .right{flex:1}

两个div是嵌套关系,里面的div垂直水平居中

display:flex;justify-content:center;水平alifn-items:center;垂直; position:absolute; left:50%; top:50%;transform:translate(-50% -50%) ; postion:absolute; top:0;left:0;bottom:0;rigth:0,margin:auto;

bfc、ifc、gfc、ffc

bfc就是一个块级上下文,是一个独立的区域,在这个区域中外部的属性影响不到里面定位 弹性盒都可以形成一个BFC,也就是 使用了弹性盒 那么就形成一个独立的区域 这一区域 不会受外在属性的影响 浮动、定位可以引起。 IFC 内联格式上下文 GFC 网格布局格式化上下文 FFC 自适应格式上下文

标准盒模型、怪异盒模型

标准盒模型(W3C盒子模型):设置的宽高是对实际内容(content)的宽高进行设置,内容周围的border和padding另外设置,即盒子模型的width(高)=设置的content的宽(高)+padding+border+margin; 怪异盒模型(IE盒子模型):设置的宽高是对实际内容(content)+内边距(padding)+边框(border)之和的宽高进行设置的, 其盒模型的width(height)=设置的width(height)+外边距margin; 解决两者的兼容问题:可尝试对父元素使用内边距,对子元素使用外边距

渐进增强和优雅降级的区别

渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验; 优雅降级:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容;

css选择器

元素选择器:元素名称{color:#f00}; 属性选择器:元素名称[标签]----元素名称Element 标签attribute; ID选择器:#id属性值{color:#f00}; 类class选择器:.属性值{color:#f00}; 伪元素选择器:p::first-line{}、::before、::after、::selection; 伪类选择器:a:link、:hover、:active、:focus、:first-child; 包含选择器:div下所有的class=‘nian’标签div .nian{color:#f00}; 子选择器:父子关系div1>div2; 兄弟选择器:同级向下的标签选择.java~li{};

position的四种

relative:相对定位,相对于其正常(本身)位置进行定位,可以z-index层次分级; absolute:绝对定位,设置元素相对于其父元素左上角的位置,如果父元素设置了static,子元素会找到body为止; fixed:固定定位,相对于浏览器窗口进行定位,位置可以改上下左右属性,可以通过z-index进行层次分级; static:静态定位,是position属性的默认值,无论怎么设置上下左右属性,元素的位置都不会发生改变;

em、rem、px、vw、vh单位的区别

px是固定长度单位,不随其它元素的变化而变化。 em是相对于父级元素的单位,会随父级元素的属性(font-size或其它属性)变化而变化。 rem是相对于根目录(HTML元素)的,所有它会随HTML元素的属性(font-size)变化而变化。是基于html的字体大小进行布局的,会除以16px。 vw、vh:vw根据窗口的宽度,vh根据窗口的高度;在pc端中指的是浏览器可视区域,在移动端中指的是布局视口;主要用于页面视口大小布局,在页面布局上更加方便。function pixel2vw(pixel) {return ((pixel / 750) * 100) + 'vw';}

css、less、sass的区别

less:是基于js,在客户端处理的,变量用@,只能用递归函数循环数值,扩展了css语言,增加了变量、Mixin,函数等; sass:是基于ruby,在服务端处理的,变量用$,可以遍历任何类型的数据,支持条件语句,可以用if{}else{}for{}循环,less不支持;

为什么css中用translate来改变位置而不是定位

translate不会触发浏览器重新布局

css绘制三角形

1、{border: 50px solid transparent;border-bottom:50px solid 颜色}

js

ts

基础类型:number、string、boolean、arrar、object。 enum:枚举;type、interface;typeof;联合类型;交叉类型。 ts是js的加强版,添加了可选的静态类型和基于类的面向对象编程; 包含类和接口的概念;可以明确指定数据类型,代码可读性强,方便特性

基本引用数据类型

基本数据类型:number、string、boolean、null、undefined、symbol(独一无二的值);存放在栈中,是一段简单的数据段,数据大小确定,内存空间大小可以分配,是直接按值存放的,可以按值访问。 引用数据类型:Object、Array、Function、RegExp、date;存放在堆中,变量在栈中保存的是指向堆内存的地址值,这个地址值指向对应的对象类型,访问堆内存中的对象是通过地址值访问的。

区分基本引用数据类型: typeof:基本数据类型除了null判断为object,都能判断出来;引用数据类型除了function能判断出来,其他判断是object。 instanceof:测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。即判断对象是否是某一数据类型(如Array)的实例。只有引用数据类型(Array,Function,Object)被精准判断,其他(数值Number,布尔值Boolean,字符串String)等基本数据类型不能被instanceof精准判断。 constructor;Object.prototype.toString.call()

说下es6

es6是es5的下一个版本,目前浏览器对es6的支持不是特别好,需要用babel对es6进行编译变成浏览器能识别的es5, 是在es5基础上新增了一些语法 let const 定义变量的方法, 箭头函数、解构赋值、回调函数, 数组的一些方法:Array.from、Array.of、find、findIndex、includes、flat;Promise

遍历对象的方法: 1、for in:for(let k in obj); 2、Object.keys、Object.values

let、const、var

var:是全局声明,有变量提升,会造成重复赋值,循环里的赋值可能会造成变量泄露至全局,var和function的全局声明会自动绑定到window, 但是let和const不会; let:是块级作用的,只适用于当前代码块,没有变量提升,let在一个块级作用只能赋一次值,并进行当前代码块的锁区,就是说当前块只有let声明的这个变量是有用的;

let、const会造成暂时性死区, 只要块级作用域内存在let命令,它所声明的变量就会"绑定"这个区域,不在乎外部的影响。 如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成封闭作用域。 凡是在声明之前就使用这些变量,就会报错。这就是暂时性死区。 const定义的对象是可以改变的,因为const定义的知识那个指向对象的地址,地址不变,地址指向的位置的内容是可以改变的。

暂时性死区

只要块级作用域内存在let命令,它所声明的变量就会"绑定"这个区域,不在乎外部的影响。 如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成封闭作用域。 凡是在声明之前就使用这些变量,就会报错。这就是暂时性死区。

promise

Promise 有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。 但是无法获取到pending状态,在promise中接受两个内置参数分别是resolve(成功)和reject(失败), Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。 then方法可以传递两个回调函数第一个是成功,第二个是失败,失败回调也可以使用promise的catch方法回调, promise还有一个强大的功能那就是all方法可以组合多个promise实例,包装成一个新的 Promise 实例 解决回调地狱、异步变同步。

链式调用:后面的then需要前面的then的返回值,then返回promise对象。

async await比promise,实现简单更易于调试

call、apply和bind区别

相同点:作用相同,都是动态修改this指向;都不会修改原先函数的this指向。 call和apply是改变后页面加载之后就立即执行,是同步代码。 call、apply只是临时的修改一次,也就是call和apply方法的那一次;当再次调用原函数的时候,它的指向还是原来的指向。 bind是异步代码,改变后不会立即执行;而是返回一个新的函数。 bind是永久修改函数this指向,但是它修改的不是原来的函数;而是返回一个修改过后新的函数,此函数的this永远被改变了,绑定了就修改不了。 apply第一个参数是指定的对象,第二个是数组; call和bind是一个一个逐一传入,不能使用剩余参数的方式传参 什么时候调用:改变this指向的时候

async await函数

async 会将其后的函数(函数表达式或 Lambda)的返回值封装成一个 Promise 对象,而 await 会等待这个 Promise 完成,并将其 resolve 的结果返回出来。

async await是处理异步代码的新方式,使异步代码更像同步代码 async await 是基于promise实现的,默认返回一个promise实例,不能被改变 await 只能在async函数中使用,不能在普遍函数中使用,要成对出现 await 下面的代码是异步,后面代码是同步

闭包

读取其他函数内部变量的函数。闭包场景:防抖节流

内存泄漏

内存泄漏:程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但是内存泄漏堆积后的结果就是内存溢出。 会引起内存泄漏:闭包、意外的全局变量、被忘记的定时器或回调函数。

垃圾回收机制

垃圾回收机制就是 js会周期性的回收一些不再使用的变量来释放内存。 解决方法: 标记清除:垃圾回收机制给存储在内存中所有的变量加上标记,然后去掉环境中的变量以及被环境中变量(闭包),之后内存总仍存在标记的变量就是要删除的变量,垃圾回收机制将这些带有标记的变量回收; 引用计数:垃圾回收机制给一个变量一个引用次数,当声明了一个变量并将一个引用类型赋值,给该变量的时候这个值的引用次数就加1,当变量的值变成另外一个值,则这个值的引用次数就减1,当这个值的引用次数变为0的时候,说明没有变量在使用,垃圾回收机制会在运行的时候清理引用次数为0的值所会占用的空间;

防抖和节流

防抖:在事件被触发n秒后在执行回调函数,如果在这n秒内又被触发,则重新计算。 使用场景:按钮的疯狂点击、 search搜索联想,用户在不断输入值时,用防抖来节约请求资源。 节流:规定在一个单位时间内,只能触发一次该函数,如果这个单位时间内触发多次函数,只有一次生效。 使用场景:鼠标不断点击触发,mousedown(单位时间内只触发一次) 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断;实时请求接口

js继承方式

原型链继承:将父类的实例作为子类的原型, 缺点:引用类型的属性被所有实例共享,在创建Child的实例时,不能向person传参,创建子类实例时,无法向父类构造函数传参,无法实现多继承。 组合继承:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用; 特点:既是子类的实例,也是父类的实例,可传参,函数可复用; 缺点:调用了两次父类构造函数,生成了两份实例。 拷贝继承:特点:支持多继承, 缺点:效率较低,内存占用高。 构造继承:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)。 类继承。

深拷贝和浅拷贝

浅拷贝:复制的是内存地址,原地址中对象被改变了,复制出来的也会相应改变; 数组:Array.slice、遍历复制数组:for()、map、filter、while、reduce,Array.concat、...扩展运算符、Array.from、解构赋值; 对象:Object.assign、...扩展运算符、Array.prototype.concat()、Array.prototype.slice()、解构赋值; 深拷贝:创建一个对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址; 数组对象:JSON.pase(JSON.stringify())、递归:自己调用自己、函数库lodash; JSON.pase(JSON.stringify())的弊端:1.如果是时间对象,就只会是字符串形式,而不是时间对象 2.如果是函数,会把函数或者undefined丢失;如果是NaN、infinity和-infinity,结果是null。

缓存机制

浏览器分为强缓存和协商缓存。 触发的前后顺序不同:强缓存在前,协商缓存在后; 资源未过期触发强缓存,资源过期后再触发协商缓存; 判断过期的方法:expired绝对时间、cache-control相对时间; 判断资源是否有更新:last-modified和etag; 浏览器先根据这个资源的http头信息来判断是否命中强缓存。如果命中则直接加载缓存中的资源,并不会把请求发送到服务器。如果未命中强缓存200,则浏览器会将资源加载请求发送到服务器,服务器来判断本地缓存是否失效;若可以使用,则服务器并不会返回资源信息,浏览器继续从缓存加载资源;如果未命中协商缓存304,则服务器会将完整的资源返回给浏览器,浏览器加载新资源,并更新缓存。

undefined和null的区别

undefined:表示缺少值,即应该有值,但是还没有赋予(变量提升时默认会赋值为undefined,函数参数未提供默认为undefined,函数的返回值默认为undefined); typeof的数据类型是undefined,Number(undefiend)|+undefined//NAN; null==undefined(true),null===undefined(false)。 null:表示没有对象,即不应该有值,经常用作函数的参数,或作为原型链的重点; typeof的数据类型是object,Number(null)+null//0;

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

箭头函数:使用箭头定义,全都是匿名函数; 不能用于构造函数,没有new关键字,否则会抛出错误; call、apply、bind不能改变this指向; 箭头函数没有this,所以this指向固定,指向它的父级; 不能使用arguments对象,但可以使用rest参数; 不能作为generator函数使用,没有yield命令;没有原型属性。 普通函数:可以有匿名函数,也可以有具名函数; call、apply、bind不能改变this指向; 可以用于构造函数,以此创建对象实例,this指向创建的对象实例; this总是指向调用它的对象; 在严格模式下,如果没有找到直接调用者,this指向undefined; 在默认情况下,如果没有找到直接调用者,this指向window。

箭头函数优点: 1、隐式返回,如 下面的代码可以去掉return,代码移到一行,减少代码量。 2、写法简单。 3、解决了this指向问题,原生的写法this指向的是调用者,箭头函数this绑定的是定义时的那个对象。如果有对象嵌套的情况,this绑定到最近的一层对象上。 箭头函数的缺点: 1、作为构造函数时不能使用箭头函数 2、真正需要this的时候,如给元素绑定click事件的时候,执行的回调函数不能使用箭头函数 3、我们需要使用arguments对象时不能使用箭头函数,箭头函数没有arguments对象。

对象的创建方式

1.对象字面量 2.用function来模拟无参的构造函数 3.用function来模拟参构造函数来实现(用this关键字定义构造的上下文属性) 4、用工厂方式来创建(内置对象) 5、用原型方式来创建 6、用混合方式来创建

new创建对象和字面量创建对象的区别

new创建对象是实例化,需要调用object方法;字面量创建对象是直接创建。 new创建:创建一个新对象, 将新对象的_proto_指向构造函数的prototype对象, 将构造函数的作用域赋值给新对象 (也就是this指向新对象), 执行构造函数中的代码(为这个新对象添加属性), 返回新的对象。

为什么js是单线程

避免复杂性,多线程操作dom会很混乱,作为浏览器脚本语言。主要用途就是用户互动,操作dom,就决定了它只能是单线程

js的事件循环机制

代码是从上到下一行一行执行的;如果某一行报错,则停止执行下面的代码;先执行同步代码,再执行异步代码;微任务比宏任务执行时机要早

js是一个单线程,这个线程分同步异步,先执行同步再执行异步,异步分微任务和宏任务,先微任务再宏任务

微任务:promise.then .catch .finally、process.nextTick 宏任务:setTimeout、setInterval、setImmediate、console.log

js事件处理机制:捕获、目标、冒泡

interface和type有什么区别

interface定义数据的形状,具体这个数据结构如何,有哪些属性; type定义数据的类型,一个数据具体值是什么类型

this指向

this是执行上下文环境的一部分,而执行上下文需要在代码执行之前确定,而不是定义的时候。this的值是在执行的时候才能确认,定义的时候不能确认 全局作用域下的this指向window 如果给元素的事件行为绑定函数,那么函数中的this指向当前被绑定的那个元素 (如果汉字中有this,this指向上一级,否则,指向window) 函数中的this,要看函数执行前有没有.,有.的话,.前面是谁,this就指向谁,如果没有,指向window 自执行函数中的this永远指向window 定时器中函数的this指向window 构造函数中this指向当前实例 call、apply、bind可以改变函数的this指向 箭头函数中没有this,如果输出this,就会输出箭头函数定义时所在的作用域中的this

面向对象 --- 封装

js是一个基于原型的面向对象的语言,每一个对象都有一个原型

面向对象编程,使用构造函数构造对象(面向对象是一种编程思想 符合我们的生活逻辑)

  1. 先书写一个构造函数
  2. 在构造函数内向对象添加一些成员
  3. 使用这个构造函数创造一个对象(和 new 连用)
  4. 构造函数可以创建对象,并且创建一个带有属性和方法的对象
  5. 面向对象就是要想办法找到一个有属性和方法的对象
  6. 面向对象就是我们自己制造构造函数的过程

构造函数,构造函数的执行过程,和普通函数的区别

构造函数也是一个普通函数,创建方式和普通函数一样,但构造函数习惯上首字母大写 构造函数:调用方式:需要使用new关键字调用;构造函数的函数名与类名相同:既是函数名,也是这个对象的类名;作用:构造函数用来新建实例对象;内部用this 来构造属性和方法 普通函数:调用方式:直接调用

构造函数的执行流程: A、立刻在堆内存中创建一个新的对象 B、将新建的对象设置为函数中的this C、逐个执行函数中的代码 D、将新建的对象作为返回值

全局作用域和局部作用域

全局作用域:在页面打开时创建,页面关闭时销毁;全局作用域中有一个全局对象window,可以直接使用。所有创建的变量都会作为window对象的属性保存;所有创建的函数都会作为winow对象的方法保存。 局部作用域(函数作用域):在函数内部就是作用域,这个代码的名字只在函数的内部起作用;调用函数时创建函数作用域,函数执行完毕之后,函数作用域销毁;每调用一次函数就好创建一个新的函数作用域,它们之间是相互独立的。

原型和原型链的区别

原型:prototype,每一个函数都有一个prototype属性,为显示原型;proto,每一个实例对象都有proto属性,为隐式原型;constructor,每一个prototype原型上都有一个constructor属性,指向它关联的构造函数。 原型链:获取对象时,如果对象本身没有这个属性,就去原型proto上找,如果还差不到,就去找原型的原型,一直找到最顶层Object.prototype为止。Object.prototype对象也有proto属性值为null。

回调地狱和回调函数

回调地狱:函数作为参数层层嵌套看起来很好理解,实际上就是我们在做原生JS的时候产生的回调函数,因为函数闭包特性,所以产生层级嵌套 回调函数:作为参数传递给另一个函数的函数,然后在外部函数内调用该函数以完成某种例程或操作。一个回调函数,也被称为高阶函数。

以下方式避免回调地狱: 模块化:将回调函数转换为独立的函数 使用流程控制库,例如[aync] 使用Promise 使用aync/await

事件流

事件流描述的是页面中接受事件的顺序,微软为事件冒泡,网景为事件捕获。 事件捕获 从上向下传播; 事件冒泡 从下向上传播;

函数柯里化

柯里化又称部分求值,字面意思就是不会立刻求值,而是到了需要的时候再去求值。 柯里化的作用: 延迟计算:上面的例子已经比较好低说明了。 参数复用:当在多次调用同一个函数,并且传递的-参数绝大多数是相同的,那么该函数可能是一个很好的柯里化候选。 动态创建函数:这可以是在部分计算出结果后,在此基础上动态生成新的函数处理后面的业务,这样省略了重复计算。或者可以通过将要传入调用函数的参数子集,部分应用到函数中,从而动态创造出一个新函数,这个新函数保存了重复传入的参数(以后不必每次都传)。

数组去重

1、set去重:new set(arr)。 2、filter去重:arr.filter((item,index) => arr.indexOf(item) === index),filter创建新数组,indexOf查询数组的下标,看是否等于当前的下标,相等就返回,否则不返回值。 3、for 循环 搭配 indexOf 去重:newArr.indexOf(arr[i]===-1)indexOf判断数组中有没有字符串值,没有就返回-1。 4、将数组的每一个元素依次与其他元素做比较,发现重复元素,删除 比较繁琐 不推荐。 5、借助新数组 通过 indexOf 方法判断当前元素在数组中的索引,如果与循环的下标相等则添加到新数组中。 6、利用双重for循环。 7、for循环+includes实现数组去重:!newArr.includes(arr[i])

普通函数和声明一个函数区别

优先级不一样,声明一个函数的优先级高

函数外部能访问到函数内部的var变量吗

访问不到,虽然var是全局声明,但是函数声明优先级大于变量声明

set和map

应用场景Set用于数据重组,Map用于数据储存 Set:  (1)成员不能重复 (2)只有键值没有键名,类似数组 (3)可以遍历,方法有add, delete,has (4)所有的元素都会被自动排序 (5)不能通过迭代器来改变set的值,因为set的值就是键 Map: (1)本质上是健值对的集合,类似集合 (2)可以遍历,可以跟各种数据格式转换 (3)所有元素是通过键进行自动排序 (4)map的键是不能修改,但是其键对应的值是可以修改的

同步和异步

怎么实现异步变同步: 1.使用async await 2 先使用promise然后使用.then可以按照同步的方式执行下一个操作

数组中哪些方法会改变原数组

会改变:pop、push、shift、reverse、unshift、sort、splice 不会改变:filter、some、every、concat、map、slice

时间复杂度和空间复杂度

时间复杂度:就是说执行算法需要消耗的时间长短,越快越好。 比如你在电脑上打开计算器,如果一个普通的运算要消耗1分钟时间,那谁还会用它呢,还不如自己口算呢。 空间复杂度:就是说执行当前算法需要消耗的存储空间大小,也是越少越好。 本来计算机的存储资源就是有限的,如果你的算法总是需要耗费很大的存储空间,这样也会给机器带来很大的负担。

数组自定义长度进行分割

对象数组根据相同属性聚合

react

mvvm

MVC 有一个巨大的缺陷就是控制器承担的责任太大了,随着项目愈加复杂,控制器中的代码会越来越臃肿,导致出现不利于维护的情况。 MVVM:viewModule监听器,ViewModel 只关心数据和业务的处理, 不关心 View 如何处理数据,在这种情况下,View 和 Model 都可以独立出来,任何一方 改变了也不一定需要改变另一方,并且可以将一些可复用的逻辑放在一个 ViewModel 中,让多个 View 复用这个 ViewModel。

react和vue的区别

react 整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以react中,是单向数据流;react中没有指令、计算属性、watch监听、computed这些内容,在react组件中,只有这几个概念,生命周期、state、props、合成事件;react没有指令概念,用受控组件完成双向数据绑定 vue 的思想是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom,v-model可以完成控件和属性值的同步(双向数据绑定)。 组件嵌套:vue可以用v-slot实现组件嵌套;react用this.props.children,也可以将嵌套内容当成props传递

diff算法

react diff 是为了在组件更新的时候,实现最小更新,减少dom操作,只更新修改的部分。 区别于传统diff,react的diff算法的时间复杂度低 react的diff只考虑同层级节点的对比,不考虑跨层级移动,在react的diff主要分为这么几个部分 如果元素类型发生变化,直接替换 如果是文本,则比较文本里面的内容,是否有差异 如果是元素就需要比较当前元素的属性是否相等,会先比较key 在react的diff主要分为这么几个部分

  • 文本节点对比,dom元素类型对比,dom元素属性对比,dom元素子节点对比,子节点位置更新,组件更新
  • 在子节点diff的时候为了能够更快的找到对应元素,在react中列表我们都需要为每一个元素添加key。在diff元素的过程中优先对比有key的元素进行更新
  • 然后判断元素位置(未发生位置变化,当前位置新增,当前元素的下一个元素与新节点相同,那么删除当前节点下一个节点向前移动,当前元素有,但是与更新后的当前位置元素不同,下一个也不同,那么把新元素插入到当前位置元素的前面)
  • 组件更新,先判断当前组件的构造函数是否相同,如果相同直接更新props,否则卸载当前位置组件,创建新组件进行替换

什么是hook

是react16.8之后推出的一个新功能,用于在Class给函数组件提供class组件的一些能力,让函数式组件可以有状态和生命周期,可以很大程度上减少代码量,分离业务逻辑。 useState:可以在函数内部实现状态; useEffect:模拟生命周期,componentDidMount、componentDidUpdate、componentWillUnmonut; useContext:跨组件传值; useReducer:useState加强版,在某些场景下,比useState更适用,例如state逻辑较为复杂且包含多个子值,或者下一个state依赖于之前的state; useMemo:缓存数据;useCallback:缓存函数,都是在组件第一次渲染时执行,之后会在其依赖的变量发生改变时再次执行。 useRef:获取节点数据; useHistory:获取到一个history对象,路由跳转 useLayoutEffect

自定义Hooks,函数名称以use开头的方法在函数内部使用

使用hooks遇到的坑: 1、useState初始化只初始化一次; 2、useEffect内部不能修改state; 3、useEffect第二个参数是引用数据类型会出现死循环; 4、react闭包陷阱,例如:setInterval,解决:clearInterval,清除重建;useRef可以解决,使用对象的引用,直接获取对象本身的数据

react通讯

父子:props 子父:函数 兄弟:代理父组件、redux 跨级:redux、context

react生命周期

错误处理:componentDidCatch 组件将要挂载时触发的函数:componentWillMount 组件挂载完成时触发的函数:componentDidMount 是否要更新数据时触发的函数:shouldComponentUpdate 将要更新数据时触发的函数:componentWillUpdate 数据更新完成时触发的函数:componentDidUpdate 组件将要销毁时触发的函数:componentWillUnmount 组件将要接收到属性的时候调用:componentWillReceiveProps 组件接受到新属性或者新状态的时候:shouldComponentUpdate

react创建组件的方式

class创建(有状态组件):通过继承react.Component实现组件的创建 函数创建(无状态组件):函数接收一个参数,是props属性,有返回值返回虚拟DOM hooks:可以在函数内部模拟状态,模拟生命周期 类组件和函数组件的应用场景: 函数组件:操作非常简单,能够实现的功能非常简单,只是简单的调取和返JSX而已,展示组件。 类组件:操作相对复杂一些,可以实现一些更为复杂的业务场景。 能够使用生命周期函数操作操作业务。 函数式组件可以理解为静态组件(组件中内容调取时已经固定了,很难在修改),而类这种方式,可以根据组件内部的状态来动态的更新和渲染内容。

setState

在react中用来修改state状态的,接收一个对象里是要改变的属性的集合,第二个参数是回调函数,更新完执行的回调函数 有同步和异步的操作,只要在生命周期和合成事件中调用setState,异步,多次调用只会合并成一次,其他是同步,像原生事件和setTime

redux流程;中间件原理;传的参数有哪些;使用场景

redux的工作流程:就是view层触发一个action到dispatcher,dispatcher将aciton传入reducer进行计算,得到新的state后传入view层进行状态更新。 中间件原理:改装dispatch。action和store之间沟通的桥梁就是dispatchr,正常store.dispatch直接把action传递给store,action只能是个对象。 用thunk的话action可以是函数,action到store之前会走中间件,中间件会把函数式的action转换成对象action再传递给store。

state和props区别

props 一般用于父组件向子组件通信,在组件之间通信使用,为只读属性; state 一般用于组件内部的状态维护,更新组建内部的数据,状态,更新子组件的props等;

什么是合成事件

React中,所有事件都是合成的,可以通过 e.nativeEvent 属性获取原生DOM事件。浏览器兼容,实现更好的跨平台 顶层事件代理机制:保证冒泡一致性,可以跨浏览器执行。将不同平台事件模拟成合成事件; 避免垃圾回收 React引入事件池,在事件池中获取或释放事件对象; React事件对象不会被释放掉,而是存入一个数组中;当事件触发,就从这个数组中弹出,避免频繁地创建和销毁(垃圾回收); 方便事件统一管理和事务机制 合成事件和原生事件的区别 命名方式不同 原生:onclick(纯小写) React:onClick(小驼峰) 事件处理函数写法不同 原生事件处理函数为字符串,React JSX语法中,传入一个函数作为事件处理函数 阻止默认行为方式的不同 原生事件:通过返回false 方式阻止默认行为; React:显式使用preventDefault() 方法阻止;比如阻止

高阶组件

高阶组件 本身不是一个组件,而是一个函数; 其次,这个函数的参数是一个组件,返回值也是一个组件

属性代理:将多个组件都需要的属性通过高阶组件进行代理,react内部也有类似组件的实现(withRouter代理路由相关属性) 反项继承:将多个组件共同的逻辑进行复用 异步高阶:react实现异步组件的加载

高阶组件和继承哪个更好?尽量不要使用继承,组合优于继承,react组件化就是把一些组件合在一起组合类型的设计模式, 可维护性比继承好的多,高阶组件就是一个函数,参数是函数,返回是函数,对组件进行了包装返回一个新的组件, 嵌套多个组件的时候,高阶组件地狱的问题,hook可以解决

受控组件和非受控组件的区别

受控:组件的改变完全受控于数据的变化,数据变了页面跟着变 非受控:input框直接操作dom,不做数据绑定,输入完成点击按钮时直接通过refs去拿dom上的内容进行操作, 实际上直接去拿dom上的数据,而不是去通过数据来控制dom的内容 受控组件更好,数据驱动是react的核心,组件都应该被数据控制,都应该是受控组件

render

render有两个,一个是组件的生命周期,一个是reactdom的render用来将react元素转换成真的dom渲染到页面上

函数组件怎么做性能优化

函数组件比普通组件性能高,因为函数没有类的生命周期,相对于类来比的话就没有构造类的一个过程,直接执行函数就行 性能低的话就是,props发生变化的话,函数就会重新执行 react.memo,可以对函数组件进行包装,就带有了shouldComponentUpdate的特性,不用构造自己的生命周期函数, 只是函数执行,可以避免重新渲染

react性能优化

pureComponent内部自带shouldcomponentUpdate,是浅比较,和immutable库结合 Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。 Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。 同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了Structural Sharing(结构共享), 即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。

虚拟dom是?为啥虚拟dom会提升代码性能?

虚拟dom就是真实dom的JS对象,比较两个内容的差异进行dom的比对,真实dom有事件,属性,背后有各种各样的方法, 所以真实dom比对非常耗性能,变成js对象就没有其他的东西,js对象的比对,就会提高性能。

ref是一个函数,有什么好处

方便react销毁组件的时候,重新渲染的时候,去有效是帮助清空ref引用的东西,防止内存泄露 内存bai泄漏指由于疏忽或错误造成程du序未能释放已经不再使zhi用的内存的情况。 2、一般dao我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的,使用完后必须显式释放的内存。应用程序一般使用malloc,calloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则这块内存就不能被再次使用,就是这块内存泄漏了。

react严格模式

react严格模式:检测意外的副作用;检测过时的 context API;确保可复用的 state。 识别不安全的生命周期、使用过时字符串 ref API 的警告、使用废弃的 findDOMNode 方法的警告

react新增的生命周期

static getDerivedStateFromProps(纯函数) 触发时间:挂载组件时,该静态方法会在render前执行;更新组件时,该静态方法会在shouldComponentUpdate前执行, 每次接收新的props之后都会返回一个对象作为新的state,返回null则说明不需要更新state。 getSnapshotBeforeUpdate: 触发时间: update发生的时候,在render之后,在组件dom渲染之前。 返回一个值,作为componentDidUpdate的第三个参数。 配合componentDidUpdate, 可以覆盖componentWillUpdate的所有用法。

dva的数据流

数据的改变通常是通过用户交互行为或者浏览器行为(如路由跳转)触发的,当此类行为会改变数据的时候可以通过dispatch发起一个action, 如果是同步行为会直接通过reducers改变state,如果是异步行为会先触发effects然后流向reducers最终改变state, 所以在dva中,数据流向非常清晰简明,并且思路基本跟开源社区保持一致

vue

diff算法

diff算法的本质,就是他是找出两个对象之间的差异,目的是尽可能的复用节点。 这个对象就是对应vue中的virtual dom,他是使用js对象来表示页面中的dom结构。 virtual DOM是将真实的DOM数据抽离出来,以对象的形式 模拟 树形结构,diff比较比较的也是virtual DOM。 diff算法是对操作前后的dom树 同一层 的节点进行比较,一层一层的对比,然后再插入真实的dom中来渲染。 他会给循环的列表中添加唯一标识,因为vue组件高度复用,增加了key可以识别组件的唯一性。这样diff算法就可以正确的识别次节点,并且找到正确的位置插入新的节点。

  • 先比较两个节点是不是相同节点
  • 相同节点比较属性,复用老节点
  • 先比较儿子节点,考虑老节点和新节点儿子的情况
  • 优化比较:头头、尾尾、头尾、尾头
  • 比对查找,进行复用

vue生命周期

数据初始化:beforeCreate, created dom 挂载:beforeMount, mounted 数据更新:beforeUpdate, updated 组件卸载:beforeDestroy,destroyed 缓存启用:activated:keep-alive 组件激活时调用。deactivated:keep-alive 组件停用时调用。

created:实例挂载前,初始化某属性值。单数服务端渲染 ssr 同一放在 created 中,因为服务端渲染不支持 mounted 方法。 mounted:实例挂载后,初始化页面完成后,对dom节点做一些操作。ajax放在mounted。 beforeUpdate:可以在这个钩子中进一步的更改状态,不会触发重渲染。 updated:可以执行依赖于DOM的操作,但是要避免更改状态,可能会导致更新无线循环。 destroyed:当前页面使用 $on ,需要解绑事件。清楚定时器。解除事件绑定, scroll mousemove可以执行一些优化操作。

vue路由模式

hash---即地址栏URL中的#符号,hash虽然出现URL中,当不会被包含在http请求中,对后端完全没有影响,因此改变hash不会重新加载页面;刷新⻚⾯时,hash 模式可以正常加载到 hash 值对应的⻚⾯;hash 可以⽀持低版本浏览器和 IE。 history---利用HTML5 History Interface 中新增的pushState()和replaceState()方法;刷新⻚⾯时, history 没有处理的话,会返回 404,⼀般需要后端将所有⻚⾯都配置重定向到⾸⻚路由。

vue导航守卫

导航守卫的意思就是监听每一个路由跳转的过程,然后提供一些钩子函数让你有机会在跳转的过程中植入相关信息。 全局路由守卫: 全局前置守卫router.beforeEach:特点:可以拦截页面跳转 ; 执行时间:在页面跳转完成之前 ;参数:to表示即将前往页面对应的路由对象 ,from 表示即将离开页面的路由对象。 全局解析守卫router.beforeResolve:特点:可以拦截页面跳转 ; 执行时间:在页面跳转完成之前 ;参数:to,from ,next 路由跳转方法 router.beforeResolve(async (to, from, next)=>{}。 全局后置钩子router.afterEach:与守卫不同,后置守卫钩子不会接受next函数,也不会改变导航本身;参数:to ,from 。 路由独享守卫:beforeEnter,路由独享守卫只在进入路由时触发,参数改变时不会触发,它们只有在从一个不同的路由导航时,才会被触发 组件内守卫: beforeRouterEnter:在路由进入之前,组件实例还未渲染,所以无法获取this实例,只能通过vm来访问组件实例 next(vm => {}) }; beforeRouterUpdate:同一页面,刷新不同数据时调用,当前路由改变,但是该组件被复用时调用; beforeRouterLeave: 离开当前路由页面时调用。

routeroute和router的区别

route是‘路由信息对象’,包括pathparamshashqueryfullPathmatchedname等路由信息参数route是‘路由信息对象’,包括path、params、hash、query、fullPath、matched、name等路由信息参数 router 是‘路由实例’对象包括了路由的跳转方法、钩子函数等; router-link、this.router.pushthis.router.push、this.router.replace、this.$router.go

vue组件传参

父传子:自定义属性props,用 refs 访问子组件,parent访问父组件,parent访问父组件,children访问父组件,root访问当前组件树的根vue实例;子传父:自定义事件root访问当前组件树的根vue实例; 子传父:自定义事件.emit,on;兄弟传参:eventBusemit调用,on接收,vuex;跨级:vuexon; 兄弟传参:eventBus,emit调用,on接收,vuex; 跨级:vuex,attrs,$listner,localStorage

v-model双向绑定原理

利用原生Object.defineProperty 这个方法来监听和改变值的, defineProperty 有两个函数: get函数 调用数据的时候触发 get方法来进行同步数据 set函数 修改数据的时候触发 渲染视图的方法 render()

v-model 是如何实现双向绑定的

vue 2.0 v-model 是⽤来在表单控件或者组件上创建双向绑定的,他的本质是 v-bind 和 v-on 的语法糖,在 ⼀个组件上使⽤ v-model ,默认会为组件绑定名为 value 的 prop 和名为 input 的事件。 Vue3.0 在 3.x 中,⾃定义组件上的 v-model 相当于传递了 modelValue prop 并接收抛出的 update:modelValue 事件

computed和watch,methods区别

watch:用于监听数据变化,其中可以监听的数据来源有三部分:props、data、computed内的数据;watch提供两个参数(newValue,oldValue),第一个参数是新值,第二个参数保存旧值 computed:计算属性,用于处理复杂的逻辑运算,主要和methods储存方法来进行区分;methods储存方法,,computed储存需要处理的数据值;methods每次都会调用,computed有缓存机制,只有改变时才执行,性能更佳 computed只有当页面数据变化时才会计算,当数据没有变化时,它会读取缓存。而watch每次都需要执行函数 场景:computed可以用于数据联动,下拉框部门选择人员;watch可以用在跳转详情,监听数据,如果数据复杂,会用到深度监听deep:true,immediate,handler。 methods:定义方法;用this.属性名直接访问到data是数据,修改data数据;在构造函数外可以使用vm.方法名定义或者调用方法。

vuex

Vuex是专门为vue提供的全局状态管理系统,用于多个组件中的数据共享、数据缓存。 问题:无法持久化。

  1. state 定义仓库的状态
  2. mutations 同步修改仓库状态的唯一途径
  3. actions 执行业务代码,方便复用,逻辑可以为异步。不能直接修改状态。修改状态过程所产生的异步代码的执行环境(处理完异步之后需调用 mutations 来修改状态)
  4. getters 属于 vuex 中的一个计算属性
  5. modules 开启 vuex 多模块形式开发
  6. namespaced 启用当前 vuex 模块的命名空间(给每个模块添加一个盒子)
  7. 补充---> 开启多模块的时候,模块之间互相调用方法的方式为 dispatch('namespace/funName', params, {root: true})

v-if和v-show的区别

频繁切换的使用v-show,不频繁切换的使用v-if。 v-if:是条件渲染,当条件成立时创建dom;渲染过程开销大,创建虚拟节点树,与旧虚拟dom比较,插入新节点,懒加载真实dom;如导航栏。 v-show:只是基于 css的display 进⾏切换,初始渲染开销大。

data为什么是函数

避免组件中的数据互相影响。如果都是对象的话,会在合并的时候,指向同一个地址。 而如果是函数的时候,合并的时候调用,会产生两个空间。

v-for 和 v-if 不建议⽤在⼀起

当 v-for 和 v-if 处于同⼀个节点时, v-for 的优先级⽐ v-if 更⾼,这意味着 v-if 将分别重复 运⾏于每个 v-for 循环中。如果要遍历的数组很⼤,⽽真正要展示的数据很少时,这将造成很⼤的性能浪费。 这种场景建议使⽤ computed ,先对数据进⾏过滤。

发布订阅者模式

发布订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。 它有两个应用场景:可以广泛应用于异步编程中,替代回调函数, 一个对象不用再显式的调用另一个对象的接口。

keep-alive

可以使被包含的组件保留状态,避免重新渲染。keep-alive包裹动态组件时,会对组件进行缓存,避免组件重新创建。 场景:一个是动态组件,一个是router-view 特性: 一般结合路由和动态组件一起使用,用于缓存组件, 提供include和exclude属性,两者都支持字符串或正则表达式,include表示只有名称匹配的组件会被缓存,exclude表示任何名称匹配的组件都不会被缓存,其中exclude的优先级比include高, 对应两个钩子函数activated和deactivated,当组件被激活时,触发钩子函数activated,当组件被移除时,触发钩子函数deactivated

vue3和vue2双向数据绑定的区别

vue2 :基于Object.defineProperty()实现 vue3: 基于Proxy, 区别: 丢掉麻烦的备份数据、省去for in 循环、可以监听数组变化、代码更简化。 1.默认进行懒观察。在2.版本里,不管数据多大,都会在一开始就为其创建观察者。当数据很大时,就可能会在页面载入时造成明显的性能压力; 在3.版本里,只会对被用于渲染初始可见部分的数据创建观察者,3.版本的观察者更高效。 2.更精准的变更通知。在2.版本里,用vue.set给对象新增一个属性时,这个对象的所有watcher都会重新运行; 在3.版本里,只有依赖那个属性的watcher才会重新运行。 vue3.使用了typescript进行重构之后各方面的性能提升都有了一个重大突破。

vue常用指令

v-once指令、v-show指令、v-if指令、v-else指令、v-else-if指令、v-for指令、v-html指令、v-text指令、v-bind指令、v-on指令、v-model指令

vue.use:全局注册一个组件或者插件。用来注册全局组件,以免在单个页面import引入 vue.set:设置data属性vue.set(data,'sex'.'男');set实例方法,也是vue.set方法的别名,主要用于当对象中某个属性值动态生成时处理方式。什么时候用set:数据没有被双向绑定时可以用vm.set实例方法,也是vue.set方法的别名,主要用于当对象中某个属性值动态生成时处理方式。什么时候用set:数据没有被双向绑定时可以用vm.set

vue自定义指令

使用Vue.directive(id,definition)注册全局自定义指令,使用组件的directives选项注册局部自定义指令。

nextTick

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。Vue中的数据更新是异步的,使用nextTick可以保证用户定义的逻辑在更新之后执行。

vue模块化

模块化就是把单独的一个功能封装到一个模块(文件)中,模块之间相互隔离,但是可以通过特定的接口公开内部成员, 也可以依赖别的模块(方便代码的重用,从而提升开发效率,并且方便后期的维护)

v-html 会导致哪些问题

xss攻击;v-html会替换标签内部的元素

vue的修饰符有哪些?

.stop、.prevent、.self、.once、.right、.center、.middle、.alt

插槽、具名、作用域插槽

插槽:在渲染父组件的时候,会将插槽中的先渲染。 如果想改变 子组件间内容的显示位置,直接调整插槽 slot 的标签位置即可。 创建组件虚拟节点时,会将组件儿子的虚拟节点保存起来。当初始化组件时,通过插槽属性将儿子进行分类 {a:[vnode],b[vnode]}; 渲染组件时会拿对应的 slot 属性的节点进行替换操作。(插槽的作用域为父组件)。 具名插槽: 名字匹配上,插槽的内容就可以显示,名字不批不显示 作用域插槽:这种插槽可以传属性和属性值。 作用域插槽在解析的时候不会作为组件的孩子节点。会解析成函数,当子组件渲染时,会调用此函数进行渲染; 普通插槽渲染的作用域是父组件,作用域插槽的渲染作用域是当前子组件。

vue性能优化

编码优化:

  • 事件代理
  • keep-alive
  • 拆分组件
  • key 保证唯一性
  • 路由懒加载、异步组件
  • 防抖节流
  • 不要在模板里面写过多表达式
  • 频繁切换的使用v-show,不频繁切换的使用v-if
  • 尽量少用float,可以用flex

vue加载性能优化:

  • 第三方模块按需导入( babel-plugin-component
  • 图片懒加载
  • 按需加载,可以用require或者import()按需加载需要的组件

用户体验:

  • app-skeleton 骨架屏
  • shellap p壳
  • pwa

seo优化:

  • 预渲染

vuex从获取数据到页面渲染的过程(bd)

计算机

浏览器输入url按下回车会发生什么

1、DNS域名解析

2、与服务器建立TCP连接

3、发起HTTP请求,发送数据

4、服务器响应HTTP请求,返回数据

5、浏览器解析数据、渲染

6、关闭连接

浏览器拿到HTML文件后,根据渲染规则进行渲染

  1. DOM 树:解析 HTML 构建 DOM(DOM 树)
  2. CSS 树:解析 CSS 构建 CSSOM(CSS 树)
  3. 渲染树:CSSOM 和 DOM 一起生成 Render Tree(渲染树)
  4. 布局(layout):根据Render Tree浏览器就知道网页中有哪些节点,以及各个节点与 CSS 的关系,从而知道每个节点的位置和几何属性(重排)
  5. 绘制(Paint):根据计算好的信息绘制整个页面(重绘)

get、post区别

get传参方式是通过地址栏url来传递, post形式url看不见的 get大小最大只能是2048个字节 post方式没有大小限制 get请求可以被缓存, post请求不会被缓存 get请求会被留在历史记录当中, post不会被留在历史记录中 get请求只支持url编码格式,post请求可以支持多种编码格式 get方式提交,安全性低,效率较高,传送的数据量较小,不能大于2KB。

同源策略

同协议,同端口、同策略,浏览器最基本的安全限制

跨域

跨域是由于浏览器的同源策略的限制,而同源策略是浏览器最基本的安全限制,同源策略限制了不同域直接无法进行ajax请求,无跨域传递cookie,无法跨域操作dom,跨域就是指协议,端口域名,有一个不同就是跨域。

怎么解决跨域

解决跨域可以通过同源策略得到特性入手解决跨域,首先同源策略是限制了ajax请求(没有限制其他请求),再就是同源策略是浏览器才会产生。解决跨域的方法主要就是: 1.jsonp:通过模拟ajax请求,突破同源策略的限制,因为jsonp发送的不是ajax请求,而是文件请求。(兼容老式浏览器); 2.代理(proxy):通过当前服务器做代理请求,因为跨域是浏览器才出现的,而服务器是不会有跨域影响的,我们可以利用当前服务器去请求真正的接口,再将数据返回给当前客户端, 正向代理:本地服务请求接口返回当前客户端(浏览器兼容处理时候); 3.cors:跨域资源共享,后端通过 Access-Control-Allow-Origin:*设置允许跨域访问的网址(开源接口)

ajax流程

1.创建ajax实例 2.执行open 确定要访问的链接 以及同步异步 3.监听请求状态 4.发送请求

url组成部分(百度)

协议、域名、端口、虚拟目录、文件名、锚、参数

浏览器内核

谷歌()、苹果(safari)、火狐()、IE()

commonjs、AMD、CMD、UMD、ES6

commonjs 同步加载,适用于服务器,node、webpack使用; AMD 异步加载,浏览器使用,实现的requirejs想兼容服务器和浏览器,预加载; CMD 异步加载,专注于浏览器,实现的是seajs,玉伯大神提出的,使用时加载; UMD AMD和commonjs的结合,可以服务端使用也可以浏览器使用; ES6 语言标准的模块化,取代UMD,服务器和浏览器都能使用;

git

冲突解决

先git checkout 切换到公共分支; git pull; 手动解决冲突; git merge合并到公共分支; 重新提交自己的代码

webpack

手动配置过吗?loader是做什么的?

webpack是一个模块化打包工具,用过配置入口和出口的方式, 根据入口模块去找对应的依赖关系在过程中通过loder和plugin去处理文件成为我们最终浏览器可识别的内容。

在react项目中配置: 安装webpack; 配置入口entry,出口output,配置模块module:loader:test:/.scss$/,loader做转换类型的,转换器; package.json:添加webpack执行命令,下载的包,项目名 webpack-dev-server,webpack.config.js新增devServer配置:hot热替换,open自动打开浏览器,port端口号; html-webpack-plugin:插件,做打包优化,文件压缩,兼容css vue项目webpack配置: vue.config.js; dllplugin提供构建和打包速度:项目根目录建dll.js文件,webpack-cli安装,package.json添加dll运行命令,npm run dll

常见的loader: image-loader:加载并压缩图片文件 json-loader:加载json文件 babel-loader:把es6转成es5 ts-loader:将typescript转成Javascript sass-loader:将scss/sass代码转换成css css-loader:加载css,支持模块化、压缩、文件导入特性 style-loader:把css代码注入到Javascript中,通过dom操作去加载css raw-loader:加载文件原始内容(utf-8)

webpack运行机制

当webpack处理应用程序时,它会根据命令行参数中或配置文件中定义的模块列表开始处理。从入口开始,webpack会递归的构建一个依赖关系图,这个依赖图包含着应用程序中所需的每个模块,然后将所有的模块打包为少量的bundle。 有了这个依赖关系树后,webpack会遍历(递归)这个依赖树,找到每个节点对应的资源文件,然后根据配置选项中的loader,交给对应的loader去加载这个模块,最后将加载的结果放入bundle.js(打包结果)中,从而实现整个项目的打包。

gulp和webpack的区别

gulp的定位是用来跑一个一个任务的。不同的任务干不同的事情,通过task定义任务的,然后通过src方法找到对应需要处理的文件, 通过pipe管道执行对应的gulp插件完成编译工作,不同的编译任务需要定义成不同的任务,使用对应的插件,是文件插件。 webpack是模块打包器,通过配置入口文件,定义输出,内部使用loader将浏览器不识别的内容(less、scss、es6) 编译成浏览器识别的内容,使用plugins来处理除了编译以为的其他任务,webpack内部实现了一套自己的模块化系统, 在webpack中一切都是模块(js、css、img)

小程序

小程序生命周期

小程序实现自定义导航,导航渐变,导航根据页面高度平滑缩小