Vue注册全局组件:
1.在Index.vue文件中建立同级文件index.js
2.在index.js中导入Index.vue,全局组件名={install:(Vue)=>{Vue.component('组件名',Index)}},然后导出全局组件名。
3.在main.js中导入index.js后,Vue.use(Index)
或者不要index.js文件,直接在main.js中导入Index.vue后Vue.component('组件名',Index)。
OSI模型:都是下层为上层提供传输服务,不关心上层传输的内容;而上层也不关心下层传输的手段,只期望能将信息最终发到通信对端的相应层次上。
以用户在电商下单为例来解释:
1.应用层-电商平台(应用软件中对应的协议,如Email-SMTP、Web-Http、文件传输-Ftp等应用层协议)。
2.表示层-木匠(负责数据编码、压缩、加密、解密等)。
3.会话层-秘书(负责文件的发送、接收,建立、管理、终结会话连接)。
以上三层也叫上层结构。
4.传输层-快递公司(TCP/UDP协议,EMS-TCP、顺丰-UDP)。
传输层也叫中间层。
5.网络层-分拨中心(路由器),在网络传输的过程中,通过IP,由路由器选择传输路径。
6.数据链路层-快递小哥(交换机),在网络传输的过程中,在网内通过物理地址(Mac地址)由交换机进行数据的传送。
7.物理层-司机大哥和交通工具(网线/光纤,负责发送比特流,提供信息传送的物理介质)。
以上三层也叫下层结构。
TCP/IP模型:
1.应用层:包含上面的应用层、表示层、会话层这三层。
2.传输层。
3.网络层。
4.网络接口层:包含上面的数据链路层、物理层。
单页面应用(SPA)和多页面应用(MPA)的区别?
单页面由一个外壳页面和多个页面片段构成。多页面由多个完整页面构成。
1.单页面首屏慢。
2.单页面搜索引擎差。
3.单页面切换快,不需要重新加载html,用户体验好。多页面需要切换html,用户体验差。
4.单页面url是hash和history模式。多页面是1.html和2.html。
5.单页面容易实现转场之间的跳转动画。
6.单页面是在同一个html中,所有传递数据比较方便,比如父子组件的传值、vuex等。
7.单页面开发比多页面难,单页面是用专门的框架来降低单页面开发的难度。
8.单页面的导航不可用,需要自己建立堆栈管理浏览器的前进后退功能。
js中简单数据类型和复杂数据类型的堆栈理解?
栈(stack):为自动分配的内存空间,它由系统自动释放。
堆(heap):是动态分配的内存,大小不定也不会自动释放。
基本类型(undefined/null/boolean/number/string):在内存中占据空间小、大小固定,所以直接在栈内存中为它分配空间,值保存在栈(stack)空间,是按值来访问。
引用类型(object/[]/function):占据空间大、大小不固定,在栈内存中为它分配空间存放引用地址,堆内存中存放对象,栈内存的地址指向堆内存中的对象,是按引用访问。
在赋值时基本类型和引用类型的区别?
1.基本类型赋值时,是直接在栈内存中重新开辟一块内存空间保存值。引用类型赋值时,是在栈内存中重新开辟一块内存空间存放一个引用地址,该引用地址还是指向原对象在堆内存中的对象。
2.访问基本数据类型时,是直接访问栈内存中其真正的值。访问引用数据类型时,是通过栈内存中的引用地址去访问堆内存中的对象。
js中垃圾回收机制的理解?
js中的内存管理是自动执行的且是不可见的。创建一个变量都需要内存。js中内存管理的主要概念是可达性(指以某种方式可访问或可用的值,它们被保存存储在内存中)。js引擎中有一个后台进程称为垃圾回收器,它监视所有对象,并删除那些不可访问的对象。
1.有一组基本的固有可达值,由于显而易见的原因无法删除。
例如:本地函数的局部变量和参数。
当前嵌套调用链上的其他函数的变量和参数。
全局变量。
其他的内部的。
这些值都称为根。
2.如果引用或引用链可以从根访问任何其他值,则认为该值是可访问的。
例子1:两个引用。var obj1={a:1};var obj2 = obj1;obj1=null;那么obj1和obj2会被释放。
例子2:相互关联的对象。如果不能从根上访问一个对象,那么该对象会被释放。
基本的垃圾回收算法为标记-清除:1.垃圾回收期获取根并标记(记住)他们。2.访问并标记1的引用。3.访问并标记2的子孙代的引用。4.进程中不能从根访问的对象被认为是不可访问的,将被删除。
js引擎对于垃圾回收机制做的一些优化:1.分代回收。2.增量回收。3.空闲时间收集。
map和set和一般对象的区别?
1.对象中的键的类型都是string。map中的键可以是任意类型。
2.一般对象,Object.keys(obj1)获取的是一个由键组成的数组。map和set数据,map1/set1.keys()返回的是一个迭代器,迭代器有next方法,且next()返回的是格式是{value:xx,done:false/true}。
3.一般对象没有iterator属性,不能使用for of方法。map和set数据有iterator属性,那么map和set数据能使用for of方法,map使用for of打印出来的是[键,值],set使用for of打印出来的是值(如果使用set.add(键,值),那么会将键打印出来)。
4.new Set一般用来数组的去重,set的方法有set.add(值)、set.delete(值)、set.has(值)、set.clear(),属性有set.size。map的方法有map.
for of遍历的是值,for in遍历的是键。[]可以使用for in和for of,一般对象可使用for in,set和map不可使用for in(不报错)。
5.set内部是使用Object.is()来实现去重,键和值是一样的,所以遍历set.keys()和set.values()的结果是一样的。set有强Set和WeakSet,WeakSet特点:只接受对象不接受简单数据类型,不可迭代不可使用for of方法,没有keys()和values()和forEach(),没有size属性。
set的方法和属性有set.add(value)、set.has(value)、set.clear()、set.size、set.keys()、set.values()、set.entries()(键值对)、forEach()。
set不是数组,不可使用数组的方法。set是无重复值的有序列表。
6.map内部是使用Object.is()来实现去重。
map的方法和属性有map.set(value)、map.has(value)、map.clear()、map.size、map.keys()、map.values()、map.entries()(键值对)。map是有序的键值对。
{}和Object.create(原型,属性(需是对象格式))和new Object()的区别?
{}和new Object()没有区别。var obj1 = Object.create(原型,属性(需是对象格式),obj1__proto__指向原型而不是Object.prototype,所以obj1不继承Object上的方法和属性。
js判断一个对象是否为空的几种方法?
1.JSON.stringify(obj1)=='{}'。
2.定义一个函数,函数里面使用for in,如果obj1不为空的话则会进入到for in里面return true,如果为空的话不会进入到for in里面return false。
3.jquery的方法,$.isEmptyObject(obj1)。
4.Object.hasOwnPropertyNames().length==0。
5.使用es6的Object.keys(obj1).length==0。
service worker使用场景:
1.后台同步:启动一个service worker,即使没有用户访问特定站点,也可以同步更新缓存。
2.响应推送:向用户发送一条信息通知新的内容可用。
3.响应来自其他源的资源请求。
4.集中接受计算成本高的数据更新,比如地理位置和陀螺仪信息,这样,多个页面就可以利用同一组数据。
5.在客户端进行CoffeeScript/LESS/CJS/AMD等模块编译和依赖管理(用于开发)。
6.后台服务钩子。
7.自定义模板用于特定URL模式。
8.性能增强,比如预取用户可能需要的资源。
service worker基本特征
1.无法操作dom.
2.只能使用https和localhost.
3.可以拦截全站请求从而控制应用。
4.与主线程独立不会被阻塞(不要在应用加载时注册sw,会)
5.完全 异步,无法使用xhr和localStorage.
6.一旦被install,就永远存在,除非uninstall.
7.独立上下文.
8.响应推送.
9.后台同步.
10.是事件驱动的worker,生命周期与页面无关,页面未关闭时,sw可退出;没有关联页面时,sw可启动。
service worker生命周期
1.注册:register。client端发起register注册一个service worker,另外需要一个sw.js文件处理sw逻辑。注册后,将作用于整个域内用户可访问的url或者其特定子集。
2.下载:用户首次防卫sw控制的网站或者页面时,sw会立刻被客户端下载。
在以下情况汇总将会触发更新:
(1)前往作用域内页面的导航。
(2)在sw上的一个事件被触发且过去24h没有被下载。
3.安装:install。如果是首次启动sw,sw会尝试安装。
如果现有sw已启动,新版本会在后台安装,但不会被激活,这个时序称为worker in waiting。直到所有已加载的页面不再使用旧sw才会激活新的sw。只要页面不再依赖旧sw,新的sw会被激活(成为active worker).
4.激活:activate。触发时可以清理旧缓存和旧的sw关联的东西。
ps:oninstall和onactivate完成前需要一些时间,sw提供了waitUntil方法,当oninstall或者onactivate触发时被调用,接受一个promise。在这个promise被成功resolve之前,功能性事件不会分发到sw。
service worker与页面的通信:
1.页面向service worker:发送navigator.serviceWorker.active.postMessage(xx);接收this.addEventListener('message',function(event){console.log(event.data)})。
2.service worker向页面:发送this.addEventListener('message',function(event){event.source.postMessage(xx)});接收navigator.serviceWorker.addEventListener('message',function(event){console.log(event.data)});
preload和prefetch特点和区别
preload特点:
1.preload加载的资源是在浏览器渲染机制之前进行处理,并且不会阻塞onload事件.
2.preload支持加载多种类型的资源,并且可以加载跨域资源。
3.preload加载的js其加载和执行的过程是分离的。即preload会预加载相应的js,待到需要时自行去调用。
prefetch特点:
1、prefetch加载的资源可以获取非当前页面所需要的资源,并且将其放入缓存至少5min(无论资源是否可以缓存);并且,当页面跳转时,未完成的prefetch请求不会被中断。
对比:
1.preload和prefetch都没有同域名的限制。
2.preload主要用于预加载当前页面需要的资源;prefetch主要用于加载将来页面可能需要的资源。
3.不论资源是否可缓存,prefetch会存储在net-stack cache中至少5分钟。
4.preload需要使用as属性指定特定资源类型以便浏览器为其分配一定的优先级,并能够正确加载资源。如果as不写,那么会当做异步请求处理。。
5.都是用link标签的ref属性:
<link ref="preload" as="script/style/image/font/fetch/document/audio/video" href="test.js" οnlοad="handleOnload()" οnerrοr="handlepreloadError()" crossorigin="anonymous/use-credentials">
<link ref="prefetch">
当资源被加载时会触发onload里面的事件。
preload/prefetch使用案例:
1.提前加载字体文件:由于字体文件必须等到cssom构建完成并且作用到页面元素时,才会加载,会导致页面字体样式闪动。所以要用到preload显示告诉浏览器提前加载。假如字体文件在css生效之前下载完成,则可以完全消灭页面闪动问题。
2.使用preload预加载第二屏的内容。在用户浏览完首屏内容滚动时能够更快的看到次屏的内容。
3.在页面加载完后,可分析页面上的所有链接,预判断用户可能会点击的页面,分析提取下一跳转页面的资源(使用prefetch),浏览器会在空闲时间进行加载,当一农户点击链接命中了缓存,这有效提升下一页面的首屏渲染时间。
4.对于商品列表页面,当鼠标停留在某个商品时,可分析商品详情页所需要的资源并提前开启preload加载,预测用户的行为并做些预加载,点击命中率更高,preload可立即加载资源,有效提升缓存命中率。
Chrome有四种缓存:HTTP缓存、内存缓存、service worker缓存和push缓存 。preload和prefetch都被存储在http缓存中。当一个资源被preload/prefetch后,它可以从http缓存移动至渲染器的内存缓存中。
浏览器预解析:
比如chrome,解析html时收集外链,并在后台并行下载,它也实现了提前加载以及加载和执行分离。
它相比于preload方式而言:
1.仅仅限于html解析,对于js异步加载资源的逻辑无效。
2.浏览器不暴露preload中的onload事件,也就无法更多细粒度的控制资源的加载。
async和defer的特点和区别:
1.async/defer在加载脚本的时候不阻塞html的解析。没有defer/async,浏览器会立即加载并执行指定的脚步,也就是说不等待后续载入的文档元素,读到script就加载并执行。
2.async表示异步执行,下载后立即执行。defer表示下载后,延迟执行,即整个文档解析完毕DOMContentLoaded事件后才执行。
2.defer只作用于js,对样式/图片无效;preload可作用于各种文件。
3.async/defer比preload的兼容性好。
4.defer加载的资源是在DOMContentLoaded时执行的;preload只下载不执行,待真正使用的时候才会执行文件。
5.对于首页上的js直接用defer,对于非首页的可以用preload/prefetch来进行加载。
html文档的加载与页面的所以渲染:
1.浏览器下载html页面。
2.浏览器解析Html页面中的dom结构。
3.开启下载线程对文档中的所有资源按优先级排序下载。
4.主线程继续解析文档,到达head节点:
head里面有同步的外链js,则停止解析后续内容,等待该资源下载,下载完后立刻知错能改。如果是外链css,继续解析后续内容。
5.解析到body:
(1).只有dom元素:dom树构建完,页面首次渲染。
(2).有dom和外链js:该js尚未下载到本地,则js之前的dom会被渲染到页面上,同时js会阻塞后面dom的构建,即在js执行之前,页面上看不到该js后面的dom元素。
(3).有dom和外链css:外链css不会影响css后面的dom构建,但是会阻碍渲染。即外链css加载之前,页面还是白屏。
(4).有dom和外链js和外链css:外链js和外链css的顺序会影响页面渲染。
当body中js之前的外链css未加载完之前,页面不会被渲染。当body中js之前的外链css加载完之后,js之前的dom树和css合并为渲染树,页面渲染出该js之前的dom结构。
6.文档解析完毕,页面重新渲染。当页面引用的所有js同步代码执行完毕,触发DOMContentLoaded事件。
7.html文档中的图片资源、js代码中有异步加载的css、js、图片都加载完毕之后,触发Load事件。
// 选择分配日期
handleSelOpeDate() {
if (this.opeDateArr && this.opeDateArr.length > 0) {
this.listQuery.BeginCreateTime = this.opeDateArr[0]
this.listQuery.EdnCreateTime = nextDate(this.opeDateArr[1])
} else {
this.listQuery.EdnCreateTime = this.listQuery.BeginCreateTime = ''
}
},
typescript和js的区别
typescript是js的超集,是js的语法糖,即typescript可以做js能做的所有事,并且能做js不能做的事。
js的弱点是:静态类型检查、代码重构、语言服务。
ps:编译时就知道变量类型的是静态类型;运行时才知道一个变量类型的是动态类型;通过已知数据类型,在编译时期推导出不知道的变量的类型是类型推导;
不允许隐式转换的是强类型;允许隐式转换的是弱类型;
js特点:
1.无需编译,由浏览器逐行加载解释执行;js是动态类型语言,也是弱类型语言。
2.js是一种基于对象的语言,但是不支持其他面向对象语言所具有的继承和重载功能。
3.js是弱类型语言。
4.js语言具有动态性。js是事件驱动的。
5.js只依赖于浏览器,与操作系统的因素无关。因此js是一种跨平台的语言。
6.兼容性好,能与xml、REST API等一起使用。
ts特点:
1.类型注释:ts采用强类型,可以看清楚每一个对象的属性、方法的参数等,本质上是良好的注释,ts通过类型注释提供编译时的静态类型检查。
2.限制变量只能访问所绑定的类型中存在的属性和方法。ts在代码编写的过程中就能进行一些代码校验,js需要执行到了对应代码才能发现错误。
3.增加了类、模块(可以把声明、数据、函数和类封装在模块中)、接口。
4.ts可用于开发大型的应用。
5.ts为函数提供了缺省参数值。
区别有:
1.语言层面:js和ts都是ECMAScriptd的具体实现。
2.执行环境层面:浏览器引擎和Node.js都能够直接运行js,但无法运行ts。
3.时序层面:ts在真正执行前,会通过编译器转换生成js后,才被解释执行。
4.厂商层面:js由Netscape推出,各大浏览器厂商实现。ts是微软设计和维护。
es6是ECMAScript第五个版本。
JS由ES(ECMAScript)、DOM、BOM组成。
Node.js里面只有ES。
ECMAScript:是js语言的标准。
es6新特性:
1.const和let。
2.解构。
3.对象字面量简写法。
4.for...of循环具有迭代器属性的数据。一般object不能使用for...of,需要给该object添加迭代器属性后,才可使用for...of。。
for...in循环遍历自身和继承和原型链上的属性。
5.展开运算符...。
6.剩余参数使用...。
6.箭头函数。
7.es5通过构造函数来创建类;es6通过class创建类(super和extends扩展类);ts中新增使用private、public等字段为访问限定符(ts编译报错不会影响es5代码的生成;ts提供抽象abstract类、抽象abstract方法、和接口继承,接口继承也是用的extends关键字)。最终都是通过es5的原型链进行继承。
typescript相对于es5有五大改善:
1.类型。
2.类。
3.注解。
4.模块导入。
5.语言工具包。
vue双向绑定数据原理
使用的是发布-订阅者模式和数据拦截。
1.Observer类:相当于是发布者。通过调用defineReactive函数,来遍历data选项里面的属性,并使用Object.defineProperty给每一个属性进行getter、setter函数来进行数据读取的拦截和监听。
在getter函数中,进行依赖收集。当数据改变的时候,就触发setter函数,调用notify函数,然后遍历watcher数组,调用watcher的update函数进行更新。
2.Dep类:相当于是调度中心。用来收集watcher和通知watcher进行更新。
每一个data里面的属性都有一个dep:{subs:watcher数组}。
3.Watcher:相当于是订阅者。给观察者属性提供回调函数和进行依赖收集。
计算属性watcher initComputed
侦听器watcher vue.prototype.$watcher里面执行
渲染watcher mountComponent
vue3.0的特性
1.在beforeCreate和created函数中间添加了setUp函数
2.添加了reactive()函数用来创建响应式数据,相当于react里面的useState()。是创建对象
3.添加了ref()函数,是对变量进行响应式处理,是创建变量。不是对象
4.添加了isRef()函数来判断对象是不是ref()函数创建出来的。
5.双向绑定数据是利用es6的Proxy来实现的。
前端五大安全问题:
1.XSS(Cross Site Scripting):跨站脚本攻击。
(1).原理:页面渲染的数据中包含可运行的脚本,来窃取包括用户身份信息在内的各种敏感信息。不需要用户做任何的登录认证,它会通过合法的操作(url中输入、在评论框中输入),向页面中注入脚本(js、html等)。
(2).攻击的基本类型:反射型(url参数直接注入,作为输入提交到服务器端,服务器端解析后响应,xss代码随着响应内容一起传回给浏览器,最后浏览器解析xss代码)和存储型(存储到DB后读取时注入,提交的代码会存储在服务器端)。
(3).注入点:html节点内的内容(text);html中dom元素的属性;js代码;富文本。
XSS的防范:(1)用户的输入检查,对数据进行严格的输出编码,使得攻击者提供的数据不再被浏览器认为是脚本而误执行。(2)将重要的cookie设置成HttpOnly。(3)服务器的输出检查。
比如将用户输入的数据进行转义;将重要的cookie标记为http only;直接过滤掉js事件标签和一些特殊的html标签;
后端服务器返回http header里面包含X-Content-Type-Options字段为nosniff,因此浏览器不会再去推断内容类型。
2.CSRF(Cross-Site Request Forgery):跨站点请求伪造。
原理:攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账户等。攻击者借助受害者的cookie骗取服务器的信任,
但是由于浏览器的同源策略,攻击者不能拿到也不能看到也不能解析cookie。
需要的条件:(1)用户登录。(2)用户点击黑客准备的网址。
防范:(1)http头中的referer检查,它记录了http请求的来源地址,但是把安全性依赖于浏览器不安全,原因:(1)IE6和FF2浏览器可以篡改referer值;(2)referer会记录下用户的访问来源,用户可以设置浏览器使其在发送请求时不再提供referer。
(2)在请求地址中添加token并验证。(3)在HTTP头中自定义属性并验证。
3.弱口令:容易被别人猜测到或者被破解工具破解的口令均为弱口令,比如简单的密码。
防范: (1)密码长度不小于8位,且由大写字母、小写字母、特殊字符、数字中的至少3种类型。
(2)密码校验成功时,发现是弱口令时强制要求用户修改登录口令后再登录。
(3)密码校验成功后,发现密码使用时间超过90d后必须强制用户修改密码才能登录。
4.暴力破解:
原理:通过大量猜测和穷举的方式来尝试获取用户口令的攻击方式。
防范:(1)避免使用弱口令。(2)对多次登录失败的账户可以锁ip或者锁定账户等机制。(3)设置验证码或者滑动验证。
5.越权访问。
原理:攻击者在获得低权限用户账户后,利用一些方式,访问或者操作到原本无权访问的高权限功能。有两种越权操作类型:横向越权操作和纵向越权操作。
垂直越权漏洞:也称为权限提升,是一种'基于url的访问控制'设计缺陷引起的漏洞。由于web应用程序没有做权限或者仅仅在菜单上做了权限控制,导致恶意用户只要猜测其他管理页面的URL,就可以访问或控制其他角色拥有的数据或页面,达到权限提升的目的。
水平越权漏洞:是一种'基于数据的访问控制'设计缺陷引起的漏洞。由于服务器端在接收到请求数据进行操作时没有判断数据的所属人而导致的越权数据访问漏洞。如服务器端从客户端提交的request参数中获取用户id,恶意攻击者通过变化请求id的值,查看或修改不属于本人的数据。
防范:垂直越权漏洞通过全局过滤器来检测用户是否登录,在对页面和访问的请求进行分权白名单等限制;水平越权漏洞,从用户的加密认证cookie中获取当前用户id,并且在执行的sql语句中加入当前用户id作为条件语句,由于cookie是加密的,所以攻击者无法修改加密信息。
es6的Symbol特性:
1.不能使用new来创建,因为是原始数据类型,不是对象。
2.相同参数的symbol返回的值是不一样的。
3.Symbol值作为属性名时,该属性不会在for...in/for...of/Object.keys()/Object.getOwnPropertyNames()中。在Object.getOwnPropertySymbols()和Reflect.ownKeys()中可以获取到。
4.Symbol.for(xx)用来检测是否有Symbol.for(xx)的属性,如有则返回,若没有就创建。Symbol.keyFor(sy)用来检测sy是否是Symbol.for()来创建的,若是返回ture否则返回false。
5.es6中使用Symbol值作为私有属性。
OSI七层网络模型:
应用层:网络用户与最终用户的一个接口,比如http/ftp/SMTP/https等。
表示层:数据的表示、安全、压缩。格式有jpge\ASCII\加密格式等。
会话层:建立、管理、终结会话。对应主机进程,表示本地主机与远程主机之间的会话。
传输层:定义数据传输的协议、端口号等,还有数据的流控和差错校验。协议有TCT/UDP。
网络层:进来逻辑地理寻址,实现不同网络之间的路径选择。如IP/ICMP/IGMP协议。
数据链路层:建立逻辑连接、进行硬件地址寻址(MAC)、差错校验等功能,传输有地址的帧。由底层网络定义协议。将比特组合成字节再组合成帧,用MAC地址访问介质,错误发现但是不能纠正。传输的是帧。
物理层:建议、维护、断开物流连接,以二进制数据形式在物理媒体上传输数据。由底层网络定义协议。传输的是比特。
前端常用设计模式:
1.单例模式:
定义:保证一个类只有一个实例,并且提供一个访问它的全局访问点。如线程池、全局缓存、浏览器中的window对象、登录浮窗等,这些对象只需要一个。
实现:用一个变量标识当前是否已经为某个类创建过对象,如果是,则在下一次获取这个类的实例时,直接返回之前创建的对象;如果否,就新创建对象。
优点:(1)在内存中只有一个对象,节省了内存空间,操作同一个共享变量来保证同步。
(2)避免频繁创建销毁对象,可以提高性能。
(3)避免对共享资源的多重占用。
(4)全局访问。
缺点:(1)违背了单一职责原则,充当了工厂角色和产品角色。
(2)长期不使用的情况下,java会自动回收。
(3)没有抽象层,继承和扩展很难。
应用场景:(1)有状态的工具类对象:设备管理器(如多台打印机),在输出同一个文件的时候只有一台打印机进行输出。
(2)需要频繁实例化然后销毁的对象:网站计数器(如统计当前的在线人数),全局对象来记录在线人数。
(3)频繁访问数据库或文件的对象:控制资源(如数据库连接池),数据库连接是一种连接数据库资源,不宜频繁创建和销毁,节省打开和关闭数据库连接所引起的效率损耗;资源共享(如应用程序的日志):一般日志内容是共享操作。
2.工厂设计模式:
参考链接:https://www.cnblogs.com/sunpengblog/p/10397986.html
(1)简单工厂设计模式:一个工厂方法,依据传入的参数,生成对应的产品对象,由工厂对象决定创建出哪一种产品类的实例。每次添加一个类,都要修改工厂类,不利于扩展,违背了开闭原则。由抽象产品、具体产品、具体工厂、产品使用者四个角色组成。所有的产品都是使用同一个new xx实例。
(2)工厂方法设计模式:对简单工厂进行抽象,将工厂提取成一个接口或抽象类,具体生产什么产品由子类决定。由抽象产品类、具体产品类、抽象工厂类、具体工厂类四个角色组成。每一个具体产品类都需要使用不同的new xx实例。
简单工厂设计模式和工厂方法设计模式,适用于产品的分类和名称是确定的,数量相对固定的,比较简单的场景。
(3)抽象工厂设计模式:为创建一组相关或者是相互依赖的对象提供的一个接口,而不需要指定它们的具体类。抽象工厂和工厂方法的区别在于抽象工厂用来生成一组产品。由抽象产品类、具体产品类、抽象工厂类、具体工厂类四个角色组成。
每一个具体工厂实现类里面里面包含多个new xx。
抽象工厂设计模式适用于一系列、大批量的对象生产。
3.观察者模式:
参考链接:https://www.jianshu.com/p/594f018b68e7
定义:定义对象之间的一对多依赖关系,使得每当一个对象的状态发生改变时,其相关依赖对象都得到通知并自动更新。由目标或主题(Subject)、被观察者(Observer)两个角色组成,是松耦合。比如EventBus、MVC等。
实现:主题对象Subject的状态有变化时,通过notify来通知Observer。目标和观察者直接关联,观察者订阅目标;目标有变化时,去触发事件来通知观察者。
4.发布订阅者模式:
定义:跟观察者模式相比较,多了调度中心。发布者通过给调度中心发布消息;订阅者订阅调度中心;有消息时,调度中心触发事件来通知订阅者。订阅者和发布者互不干扰,实现了解耦,还可以实现更细粒度的一些控制。比如通过在调度中心做一些节流处理。
typescript中的Class的修饰符:
1.public:默认是public。也可显式将一个成员标记成public。
2.private:只能在class的内部使用。当我们比较带有private和protected成员的类型的时候,如果其中一个类型里包含一个private成员,那么只有当另外一个类型中也存在这样一个private成员,并且他们都是来自
同一处声明时,才认为这两个类型是兼容的。对于protected也使用这个规则。
3.protected:protected只能在Class和子类的class内部使用。Class中protected constructor,说明此class不能被实例化,可以被继承。
4.readonly:只读。只读属性在声明时或者构造函数里被初始化。使用参数属性:直接在constructor在参数前面添加readonly,即把声明和赋值合并至一处;参数属性也可用private、public、protected。
5.存取器:通过get来获取值,通过set来设置值。只有get没有set的存取器,默认是readonly。
6.static:静态属性。静态属性只存在于类本身上面而不是类的实例上。使用类名.来访问静态属性。
6.abstract:抽象类。抽象类作为其他派生类的基类使用。不能实例化抽象类。抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。抽象方法必须包含abstract关键字并可以包含访问修饰符。
如果抽象类中没有定义某抽象方法,只在派生类中实现某方法,则派生类.某方法会报错,提示抽象类中不存在此方法。
7.高级技巧:构造函数。
在ts中声明一个Class的时候,声明了类的实例的类型;创建了一个叫做构造函数的值,这个函数会在new的时候调用。
8.把类当做接口使用。