闭包
闭包是函数中返回一个函数,函数能够访问到其父级作用域,
优点:保护变量,封装到函数内部,避免全局污染 延长变量的生命周期,即使函数执行完成后还能继续使用
缺点:内存占用,无法被垃圾回收 甚至会出现内存泄漏问题 ,闭包会设计到作用域链的查找,对性能也会有影响。
解决内存泄漏问题 从根本上来说就是对外部变量的引用,如果能够接触对变量的引用,使得其能够被垃圾回收机制释放。当然这只是最明显的,此外还有对闭包函数以及解绑函数本身的一个释放。使该变量=null进行释放
数据类型判断有四种方式
直接的有type of跟instanceof
前者主要是判断基本数据类型(除了null,null会判断成object)引用类型都会判断成object,除了function会被正常判断,
instanceof的返回值是true或者false,相反它不能判断基本数据类型(都会返回false),只能判断引用类型。
原型中的判断方式 Object.prototype.toString.call,调用slice(8,-1)就能获取到类型,均能获得
构造函数的name属性也可以进行判断
7中基本数据类型
Number,String,null,BigInt,Symbol,Boolean,Undefined
放入栈内存中
引用数据类型
Object,Array,Date,Error,Function,RegExp
放入堆内存中 在栈中存储了指针在堆中的起始位置。
generator函数生成器
function* yield 生成迭代器 next调用
浏览器工作原理
浏览器本地存储
cookie localstorage,sessionstorage,indexdDB
发布-订阅模式
vue-router
导航守卫有三类:全局守卫 路由独享守卫和组件内守卫(钩子)
两种历史记录模式
前端路由关键:
1可以修改url,在不刷新页面的情况下跳转路由
2可以监听url的变化,根据url渲染对应组件
hash模式 hash是通过location API修改url的 通过onhashchange监听hash改变
#后面的字符不会发送给服务器 seo(Search Engine Optimization搜索引擎优化)会比较差(没这么容易搜索到) 不会在服务器生成日志记录
HTML5模式 history是通过history.pushState或者history.replacestate修改url 通过popState监听
相比来说不带#号 直接在域名后写路径 优雅
Map Reduce与Filter
Map(当前值,值索引,数组本身)逐个改变数组,注意是改变,而不会生成一个新的数组
?如果不return的话也会直接改变数组
filter(当前值,值索引,数组本身),会删除数组,返回值小于等于原数组长度
reduce((累加器,当前值,值索引,数组本身)=>{},累加器初始值),值,会生成一个新的数组
foreach没有return,直接改变原数组
call apply bind
用处:改变this的指向,实现方法的继承
function.call(this指向,参数1,参数2)
function.apply(this指向,[参数])
function.bind(this指向,参数)//但不是立即执行,返回一个方法,需要手动执行
let test=function.bind()
test()执行
手写call方法
1.原型中进行绑定
1 | Function.prototype.mycall=function(context,..arg){ |
vue2与vue3的区别
vue3加入组合式api 所以没有this的操作 生命周期没有creat setup等同于create 卸载变成了unmount
vue3中的v-if高于v-for的优先级
根实例的创建从new app变成了createApp
响应式改成了proxy 解决了数组无法通过对下标修改
reactive定义的响应式数据使用proxy包装 ref使用的还是defineProperty,定义一个value属性做响应式
在组合式api时更方便按需引入 tree-shaking
性能优化 静态节点不会被标记 不会进行对比(diff)
mixin方法不被推荐 推荐用hook
v-model 用在自定义组件的时候 value/modelValue 监听事件也不一样
更好的配合ts
vue2的响应式原理
1 | function defineProperty(obj,key,val){ |
因为Object.defineProperty()无法监听到数组的方法,所以vue2中选择了直接对Object的原型进行了一个重写,使其能够监听到相应的方法。
当使用get()和set()
来获取和设置该被劫持属性的值,那么不能使用操作属性的value
和writable
属性,会冲突。当要访问被劫持属性的值,那么会触发get(),并得到的是get()中返回的值;当要修改被劫持属性的值就会触发set()
,其天生具有一个参数newVal,表示新的值
作者:前端平水
链接:https://juejin.cn/post/7268820544995901495
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Proxy
vue3实现响应式的原理,proxy进行监听,但对象本身的方法在Reflect上。
1 | const obj = new Proxy({},{ |
mvvm
一种前端的设计模式 Model模式 View视图 ViewModel视图模型
Model模式:通常是数据部分 js部分?
View视图:Html跟Css部分
ViewModel视图模型:两者之间的桥梁,将模型的数据传递给视图,将视图中的交互事件传递给模型
bfc block formatting context 块级格式化上下文
简单的来说,就是把元素块级话,在一个有父子元素的布局中,如果子元素浮动的话,此时,它的父元素因为不是一个bfc会发生坍塌,只要对元素进行bfc化就能解决这个问题。在比如就是当两个元素上下排列的时候,两个外边距坍塌,此时在中间加入一个bfc元素就可以达到没有坍塌的效果。
方法有:float:right||left position:absolute||fixed display: overflow:
单点登录single sign on
一个地方登录,所有其他的页面也是登录装态。
在不同的系统之间再设置一个共享的认证系统,每次进入系统先重定向到认证系统,系统对token资源统一管理。
主域与子域可以共享cookie 然后实现单点登录
虚拟dom
原生js是当数据放生改变时相应的dom进行更新
但是基础框架的虚拟dom是因为框架本身的一些原因,需要对全局进行一个更新,要知道操作真实dom,而且每一次都是这样牵一发而动全身的话会造成很大的性能损耗,所以就有个虚拟dom,虚拟dom完成了对全局的一个更新,再通过对新旧虚拟dom通过diff算法 进行对比,最后对相应的真实dom进行更新。虚拟dom作为中间层就完成了全量更新以及相对性能损耗较小的目的。
为了完成响应式的需求
浏览器渲染原理
先html
构建dom->构建cssom->构建渲染树->布局->绘制
遇到js代码会阻塞,等到构建渲染树时再将js代码装入。
1.样式声明(包括自定义与浏览器自带)
2.计算层叠
比较重要性(自己>浏览器默认)
比较特殊性(权重值)
比较原次序(后来者居上)
3.如果可以,从父元素中继承
4.赋予默认值
浏览器缓存
强制缓存跟协商缓存两种
强制缓存有一个cache-control跟expires,优先级是前者大于后者,前者可以设置一个最大过期时间,max-age,expires(http1.1之前的)是一个过时的字段。
协商缓存时通过etag,让客户端跟服务器进行一个对比,如果一样的话,那就直接在缓存中读取,如果不一致的话那就重新请求。
主要有last-modified(服务器返回的字段)与if-modified-since(客户端发送的字段)etag(服务器返回的字段,资源的唯一标识符)if-none-match(客户端发送的字段,客户端期待标识符)如果两者相等没有更新,不相等则代表更新了。
304状态码就是协商缓存中代表资源没有更新。
强制缓存主要用于一些静态资源,比如说(css,js,图片等)设置一个长时间的缓存。
直接赋值,浅拷贝与深拷贝
基于引用类型来说
直接赋值是赋值对象与被赋值对象指向同一块区域
浅拷贝是对引用类型的第一层是全新的赋值,但是还有更深的引用类型存在的话,这时候改变这些的话会连同原来的一起改变。
浅拷贝常用的方法数组中的slice与contact然后对象中有assign以及使用拓展运算符号filter,新的方法toSorted,toSpliced,toReversed都是返回一个新的数组而不改变原数组。
深拷贝常用的一个是JSON.parse(JSON.stringify(对象)),无法解决循环引用问题,无法拷贝特殊对象和函数
还有就是手写递归函数进行递归赋值
vuex与pinia
pinia只有state、getter,action仨,并且支持组合式的写法,在最后return回去就行了。
vuex多了mutation跟module
webpack与vite
构建速度:vite更新更快
webpack会将所有文件都打包成一个bundle 初次加载会更慢一些,热更新需要整个替换
vite利用了浏览器支持es module的特性,实现了按模块更新。