语义化:HTML 中的元素属性及属性值拥有某些含义
开发者需要遵循语义来编写HTML
好处: 代码可读性、可维护性、搜索引擎优化、提升无障碍性
CSS
选择器Selector 选择器Property 属性值:Value
页面中使用CSS:外链 嵌入 内联
CSS如何工作
加载HTML→解析HTML→创建DOM树→展示页面
↓ ↑添加样式到DOM节点
加载CSS 解析CSS
#id选择器(唯一) .类选择器 []属性选择器
^=开头是xxx $=尾部为xxx结尾
伪类:不基于标签和属性定位元素 状态伪类和结构性伪类
组合(COMBINATIONS):
直接组合AB:满足A又满足B
后代组合A B 选中B如果它是A的子孙
亲子组合A>B 如果是子元素
兄弟组合A~B 如果在A后且和A同级
相邻元素A+B 紧跟在A后面
选择器的特异度(Specificity)# . 标签计算特异度,大的优先
继承:某些属性会自动的继承父元素的计算值
显式继承
(声明值)
执行流程:filtering(选择器匹配、属性有效、符合当前media)————————> cascading(按照来源、!imporant、选择器特异性等选出一个 优先级最高的属性值)————————>defaulting(层叠值为空时,使用继承或初始)——————>resolving
(使用值) (层叠值) (指定值)
(将相对值或其他转化为绝对值)———————> constraining(将小数像素值转化为整数————————>实际值
LayOut布局:确定内容和大小位置的算法 依据元素、容器、兄弟节点和内容等信息来计算
相关技术:常规流(行级,块级,表格布局,FlexBox,Grid布局)、浮动、绝对定位
块级模型:不和其他盒子并排,适用于所有盒模型 行模型:和其他行级盒子一起放在一行或拆开成多行,盒模型中width、height不再使用
块级元素:生成块级盒子,body、article、div等
行级元素:生成行级盒子、内容分散在多个行盒中,span,em等
常规流Normal Flow:根元素、浮动和绝对定位的元素会脱离常规流,其他元素都在常规流,常规流的盒子在某种上下文排版中参与布局
行级排版上下文(IFC)只包含行级盒子的容器会创建一个IFC
块级排版上下文(BFC)根元素、浮动、绝对定位、inline-block、Flex子项喝Grid子项overflow值不是visible的快盒display:flow-root会创建一个BFC
Flex box:一种新的排版上下文,可以控制子盒子的摆放流向,顺序,盒子的宽度高度,水平喝垂直反向对其,是否允许折行
Grid布局:是元素生成一个块级的Grid容器,使用grid-template相关属性将容器划分为网格,设置占的哪格
float
JS
HTML/CSS/JS 各司其职
应当避免不必要的由JS直接操作样式
可以用class来表示状态
纯展示类交互寻求零JS方案
组件封装
组件是指Web页面上抽出来的一个个包含模板(HTML)、功能(JS)、样式(CSS)的单元
封装性、正确性、扩展性、复用性
API设计应该保证原子操作、职责单一、满足灵活性
行为:控制流,使用自定义事件来解耦
重构:插件化、模板化、抽象化(组件框架)
解耦:将控制元素抽取成插件、插件与组件之间通过依赖注入方式简历联系
过程抽象:能让一个需求覆盖不同的事件处理,我们将这个需求抽离出来,这个过程成为过程抽象
高阶函数:以函数作为参数或返回值的函数,常用于函数装饰器
常用高阶函数:Throttle,Debounce、Once、Consumer/
React
1.React组件的render函数什么时候会执行,组件初始化的时候,虚拟DOM和真实页面DOM不同的时候,用到setState的死后
2.React这种函数式编程和vue基于模板语法的前端框架的优缺点
React:创建了新的写法jsx,允许再js中编写html
vue:模板系统就是普通的html,css,js分开写,淡化了jsx的写法,更直观,项目重构更加容易
相同点:基于js的创建ui的库,轻便,组件化思想与组件化开发,虚拟dom提高渲染速度,独立的路由系统独立的状态管理
各自优势: vue模板和渲染的弹性选择,语法简洁,渲染速度更快体积更小
react:适合超大型项目,更好的可测试性,同时用于web和原生app端,更大的生态圈维护的人更多
3.React推荐使用组合而不是继承为什么?
React希望组件按照最小可用思想的原则来进行封装组件
组合的耦合程度要低于继承,也更灵活
4.MVC、MVVM
MVC:MVC允许在不改变视图的情况下改变视图对用户输入的响应方式,用户对View的操作交给了Controller处理,在Controller中响应View的事件调用Model的接口对数据进行操作,一旦Model发生变化便通知相关视图进行更新
MVVM:MVVM与MVC最大的区别就是:它实现了View和Model的自动同步,也就是当Model的属性改变时,我们<不用再自己手动操作Dom元素>,来改变View的显示,而是改变属性后该属性对应View层显示会自动改变
MVVM比MVC精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作DOM元素。因为在MVVM中,View不知道Model的存在,Model和ViewModel也观察不到View,这种低耦合模式提高代码的可重用性
HTML5 新特性
Web Fonts
(1)语义标签:<header><dialog>等
(2)增强型表单:多个新的表单input输入类型,提供更好的输入控制和验证,新增表单元素<datalist><keygen>等 ,新增属性placehoder,required等
(3)视频和音频:提供了播放音频文件的标准<audio></audio>,视频<video>
(4)Canvas绘图(5)SVG绘图(可伸缩的矢量图形):SVG和Canvas区别:SVG使用一种使用XML描述2d图像的语言,Canvas通过js来描绘,SVG每个被绘制的图形被视为对象,如果属性变换就会自动重现图形,Canvas是逐像素渲染,一旦绘制完成就不会得到浏览器的关注,位置发生变换整个场景都需要重新绘制
(6)地理定位(Geolocation)
(7)拖放API:
(8)Web worker:在HTML页面执行脚本,页面状态是不可以响应的,他是运行在后台的js,独立于其他脚本,不影响页面性能
(9)Web storage:在本地存储用户浏览数据
(10)WebSocket:提供一种在TCP链接上进行全双工的通讯协议,浏览器和服务器做一个握手的动作,两者之间就可以直接数据传输
ES6 新特性
async/await
?.(链式运算符)直接在链式调用的时候判断,左侧对象是否为null或者undefine,如果是则不继续往下运算,直接返回undefined
??(NULL判断运算符):类似||但是只有左侧为null或者undefined才生效
Object.assign:如果目标对象的属性有相同的键,则属性将被源对象的属性覆盖。
Object.entries:返回一个给定对象自身可枚举属性的键值对数组
Object.create:创建一个新对象,使现有对象来提供新创建对象的__proto__
Object.freeze:冻结一个对象,一个被冻结的对象在也不能被修改
weakMap/Map Object本质上是键值对的集合,传统上只能用字符串当作键,ES6提供Map,weakMap与Map区别,weakMap只接受对象作为键名,键名所指向的对象,不计入垃圾回收机制
BigInt是一种内置对象,提供了一种方法来表示大于2^53-1的整数
## let和const
`
let和var的区别:
let声明的变量仅在块级作用域有效,var函数作用域(for循环中设置循环变量的部分属于父作用域)
let不存在变量提升(声明的变量一定在声明后使用,否则报错(暂时性死区),var是undefined),var存在变量提升(变量提升:变量可以在声明之前使用),特别情况如果一个变量根本没有被声明,使用typeof不会报错,返回undefined
let不允许重复声明(在相同作用域),块级作用域是的获得广泛应用的匿名立即执行函数表达式不再必要
ES6明确允许在块级作用域中声明函数,此行为类似let,在块级作用域之外不可引用,但ES6附录b中规定浏览器可以有自己的执行方式①允许在块级作用域声明函数②函数声明类似var,会提升到全局作用域或函数作用域的头部③函数声明还会提升到所在块级作用域的头部
`
`
const声明一个只读的常量,一旦声明必须初始化,const的作用域和let相同只在当前作用域内有效也不提升,也存在暂时性死区。
const保证的不是变量的值不能改动,而是变量指向的那个内存地址所保存的数据不得改动(如对象可以往里面添加属性),如果想真正将对象冻结,应该使用freeze方法
`
`
ES6除了ES5的var和function命令, 还添加了let和const,import和class命令,
var和function命令声明的全局变量依旧是顶层对象属性,其他四个声明的全局变量不属于顶层属性
`
## 变量的解构赋值
`
数组的解构赋值
不完全解构:等号左边的模式只匹配一部分等号右边的数组,依然可以解构成功
`
`
对象的解构赋值
注意点:①如果要将已经声明的变量用于解构赋值,可能需要加一个圆括号()?②数组本质是特殊的对象:因此可以对数组进行对象的解构赋值
解构赋值的规则:如果等号右边不是对象或者数组,就先将其转为对象,不能对null和undefined进行解构赋值
只要有可能导致解构的歧义,就不要用圆括号
`
## 字符串的扩展
`
字符串的遍历器接口,使得字符串可以被for...of遍历
`
`
模板字符串是增强的字符串,用反引号`表示,可以当作普通字符串使用,也可以定义多行字符串,或者在字符串中嵌入变量。
模板字符串遇到需要使用`,则需要\转义
{}大括号内部可以放入任意的JS表达式,可以进行运算,可以引用对象属性,模板字符串中还能调用函数,模板字符串中还可以嵌套
`
`
标签模板:过滤HTML字符串,防止用户输入恶意内容
`
## 字符串新增的方法
String.fromCodePoint()从Unicode码点返回对应字符,这个方法改进ES5不能识别大于0XFFFF字符
String.raw()返回一个斜杠都被转义的字符串,所有斜杠前面再加一个斜杠
includes:表示是否找到了参数字符串
startsWith:表示字符串是否在原字符串头部
endsWith:是否在尾部
repeat:将源字符串重复x次
padStart,padEnd:某个字符串不够长度会在头部和尾部补全
trimStart,trimEnd:消除在头部或者尾部的空格
matchAll():返回一个正则表达式的所有匹配
replaceAll:一次性替换所有的匹配正则
at:返回参数指定位置的字符
## 数值的扩展
isFinite、isNaN、isInteger、isSafeInteger(2^53~2^-53)
parseInt、parseFloat移植到Number对象上
Number.EPSILON:一个极小的常量
Math.trunc()去除一个数的小数部分 sign()正数负数还是0 cbrt()计算立方根 clz32()将参数转为32位无符号整数的形势,返回有多少个前导0 imul()乘法,适用于有精度限制的乘法 fround() hypot()返回所有参数的平方和的平方根 expm1返回e^x-1 log1p()返回log(x+1) 双曲函数sinh、asinh
BigInt数据类型:只能表示整数,没有位数限制,任何整数都可以精确表示,BigInt数据类型后缀必须添加n
## 函数的拓展
ES6允许为函数参数设置默认值
参数默认不是传值的而是每次都重新计算默认表达式的值
函数的length属性返回没有指定默认值的参数个数
一旦设置了参数的默认值,函数进行声明初始化时会形成一个单独的作用域
ES6引入rest参数(形式为...x)用于获取多余的参数 rest参数之后不能再有其他参数,函数的length属性不包括rest参数
严格模式:ES5函数内部可以设定为严格模式,ES6规定函数参数只要使用了默认值、解构赋值或者拓展运算符就不能显式设定为严格模式
`
箭头函数:ES6允许使用箭头(=>)定义函数,如果箭头函数直接返回一个对象,必须在对象外面加上括号
箭头函数没有自己的this对象,内部的this就是定义时上层作用域中的this,指向固定,普通函数内部this是可变的
不可以当作构造函数,不可以使用arguments对象,不可以使用yeild,不能用作Generator函数
`
尾调用(Tail Call):某个函数的最后一步是调用另一个函数
尾调用优化:只保留内层函数的调用帧:只保留内层函数的调用帧
尾递归优化:不会发生栈溢出,相对节省内存
函数式编程:柯里化(将多参数的函数转化成单参数)
call:可以指定该函数内部的this指向,然后在所指定的作用域中,调用该函数。并且会立即执行该函数,this后的第二个参数是传进去函数的参数,在apply中必须以数组的形式添加
bind方法用于指定函数内部的this指向(执行时所在的作用域),然后返回一个新函数。bind方法并非立即执行一个函数。
## 数组的扩展
扩展运算符(...),有了扩展运算符就不再需要apply方法,将数组转为函数的参数,实现Iterator接口的对象都可以使用扩展运算符。背后调用的是Symbol.iterator
Array.from():将一个类似数组的对象或者可迭代的对象,转为真正的数组,Array.from第二个参数,对每个元素进行处理
Array.of():用于将一组值转换为数组
实例方法:copyWithin():将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组,会修改当前数组
find()/findIndedx():找出第一个符合条件的成员,参数为一个回调,找出第一个返回true的成员/位置。第二个参数绑定this对象
fill()用给定的值,填充一个数组
entries()/keys()/values()遍历数组:分别是对键值对、键名、键值进行遍历
includes()返回布尔值看看数组是否包含给定的值
flat/flatMap:用于将嵌套数组拉平,返回一个新的数组,参数代表拉平的层数,flat会跳过空位 flatMap:对原数组每个成员执行一个函数,对返回值组成的数组执行flat操作,只能展开一层,还可以绑定遍历函数里的this
at:跟方括号一样,不过可以支持负数
ES6明确将空位转为undefined
sort()稳定性:必须稳定
## 对象的扩展
属性可以简写,方法也可以简写,属性名可以表达式
注意,属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[object Object],这一点要特别小心。
Object.is()比较是否严格相等类似于(===)但+0 != -0,NaN不等于自身
Object.assign()用于对象的合并,将源对象的所有可枚举属性,复制到目标对象,Object.assign()方法实行的是浅拷贝,而不是深拷贝
Object.getOwnPropertyDescriptors()返回某个对象属性的描述对象(descriptor)该方法的引入目的,主要是为了解决Object.assign()无法正确拷贝get属性和set属性的问题。
Object.entries/keys/values:对象转化为数组
Object.fromEntries():将键值对数组转化成对象
## 运算符拓展
指数运算符 ** 右结合
链判断运算符 ?. 链式调用时判断,左侧对象是否是null或者undefined,如果是不继续往下算返回undefined 一般来说,使用?.运算符的场合,不应该使用圆括号。
NULL判断运算符 ?? 同最上面
逻辑赋值运算符 ||= &&= ??=
## Symbol
原因:保证每个属性的名字都是独一无二的,这样就从根本上防止属性名的冲突
Symbol 值作为对象属性名时,不能用点运算符 在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中。
Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。
Symbol.for(),Symbol.keyFor()接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值
## Set和Map
Set和WeakSet:WeakSet 结构与 Set 类似,也是不重复的值的集合 区别:①WeakSet 的成员只能是对象,而不能是其他类型的值 ②WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存
http
强缓存/协商缓存:强缓存根据cache-control和expires来判断缓存是否过期,若没过期则直接从缓存中获取资源信息,协商缓存是由服务器确定缓存是否可用,用Last-Modify/If-Modify-Since和Etag/If-None_Match判断
关于安全
XSS跨站脚本攻击:
stored XSS存储型攻击:而已脚本被存在数据库中
Reflected XSS反射型:例如在params参数中添加脚本
DOM-based XSS:
Mutation-based XSS:利用渲染DOM的特性
防御:永远不要将用户提交的信息直接变成DOM
CSRF跨站伪造请求:利用用户权限cookie构造指定HTTP请求,窃取或者修改用户敏感信息
防御:Origin+Referrer,token,避免用户信息被携带,SameSite Cookie
Injection注入攻击:
SQL Injection
CLI
OS COMMAND
Service-Side Request Forgery(SSRF),服务端伪造请求
DoS服务拒绝:通过某种方式,导致服务器资源被显著损耗,来不及响应更多请求,导致请求挤压,进而雪崩
ReDoS:基于正则表达式的DoS
Distributed DoS:短时间内来自大量僵尸设备的请求,服务器不能及时完成全部请求,导致请求堆积无法响应新请求
传输层:中间人攻击
CSP判断哪些源是安全的
WebGL
WebGL是openGL的web版
Webpack
什么是Webpack?前端资源的编译和打包工具
四个最核心的步骤:1.入口处理 2.依赖解析(处理import和export,找到依赖资源) 3资源解析(调用资源转移器,将非标准js资源转义为js内容) 4资源合并打包 (递归调用2、3直到全部资源解析完毕)
模块化+一致性:多个资源合并,减少http请求数、支持模块化开发、支持高级JS特性等等
配置分为流程类和工具类:
流程类:作用于流程中某个环节直接影响打包效果的配置项
工具类:主流程之外提供更多工程化的配置项
Loader作用:webpack默认条件下只认识.js的文件,要打包其他类型的文件需要在webpack.config.js文件中进行配置
插件作用:webpack整个生命周期中生效的一种组件
bunble chunk module:同一份逻辑代码在不同转化场景下的三个名字
Bundle:由许多modules组成,包含源码处理的最终版本————源码被加载和编译处理
chunk:webpack building过程中,bundles由许多chunks组成
modules:非连续的功能块,是webpack支持的模块
ES6 import语法会被转化为commonjs格式或者是AMD格式,babel默认会把ES6的模块转化为commonjs规范的。
TypeScript
静态类型:可读性增强:基于语法解析TSDoc,ide增强 可维护性增强:在编译阶段暴露大部分错误 多人合作项目更好的稳定性和开发效率
JS超集:包含兼容所有JS特性支持共存,支持渐进式引入与升级
回流与重绘
回流:当render树中的一部分因为各种原因改变布局需要重新构建
重绘:当render树一些元素需要更新属性只影响元素外观不影响布局就是重绘
回流必将引起重绘,重绘却不一定引起回流
Vue
Vue实例从创建到销毁的全过程就是生命周期。开始创建,初始数据,编译模板,挂载dom,渲染更新渲染,销毁一系列过程
八大钩子
beforeCreate:在实例初始化之后,data observer数据观测和event、watcher事件配置之前被调用,不可以调用Vue中的data和method等
created:实例创建完毕之后,完成了data observer,属性、方法,watch、event事件回调,可以获取到原生的html直接加载出来的dom,但是无法获取到如v-for等通过挂载模板生成的DOM
beforeMount:挂载开始前被调用
Mounted:有初始值的Dom被渲染
Vuex原理
Vuex设计思想:将数据存储到全局的store,再将store挂载到每个vue实例上,利用数据响应机制来进行高效的状态更新
原理解析:利用vue的插件机制,Vue.use(vuex)调用vuex的install方法装载vuex,再利用vue的混入机制,往beforeCreate钩子函数前混入vuexInit方法
Vue-router实现原理同vuex
MVVM 和 MVC
MVC:所有通信都是单项的。 视图(View):用户界面(传送指令到Controller) 控制器(Controller):业务逻辑(完成业务逻辑之后Model改变状态) 模型(Model):数据保存(将新的数据发送到View,用户得到反馈)
MVC允许在不改变视图的情况下改变视图对用户输入的响应方式,用户对View的操作交给Controller处理,在Controller中响应View的事件调用Model的接口对数据进行操作,一旦Model发生变化便通知相关视图进行更新
MVVM: model:服务器的业务逻辑操作 view:用户界面 viewmodel:核心枢纽
viewmodel负责把Model的数据同步到View,把View修改同步到Model
双向通信,视图和模型不发生联系,通过VM传递
双向绑定是什么原理?
Object.defineProperty。这个api能够监听到这个data的变化,在getter和setter里,当改变时调用setter。通知依赖Dep更新,依赖会有一个Watcher实例(谁订阅了这个Dep就为谁创建一个Watcher实例),数据发生变化通知Watcher实例,由其去通知真正的视图
Proxy 实现观察者模式
const person = observable({
name: '张三',
age: 20
})
function print() {
console.log(`${person.name}, ${person.age}`)
}
observe(print)
person.name = '李四'
const queuedObservers = new Set()
const observe = fn => queuedObservers.add(fn)
const observable = obj => new Proxy(obj, {set})
function set(target, name, value, receiver) {
const res = Reflect.set(target, name, value, receiver)
queuedObservers.forEach(oberver => oberver())
return res
}