-
技术
- 基础技术
- CSS
- Javascript
- 继承
- 原型链继承
- call方式继承
- 组合继承
- ES
- 继承
- 安全
- XSS
- CORS
- 设计模式 *
- 技术栈
- webpack
- webpack4新特性
- runtime.js
- webpack4新特性
- react
- Fiber Tree
- 任务优先级
- 事务
- Hooks
- 静态化
- Fiber Tree
- redux
- webpack
- 基础技术
-
工程化
-
业务
- 亮点
- 上线周期
- 商业化
- 亮点
- flex;
- absolute + box-content;
这两段JS的差别?
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fBound.prototype = this.prototype
这个问题本质是实例继承和原型链继承的区别? 第一种方法通过实例继承可以避免修改构造函数的值,第二种直接继承this.prototype; 区别有两点:
- new方式可以访问到构造函数中所有挂在this上的属性;(原型链继承的方式)
- 直接引用this.prototype则会导致,this.prototype被修改;
需要使用work-loader
,加载对应的worker.js
文件路径; work-loader
做了几件事情
- 创建一个bunld.js文件,里面有加载器逻辑和
worker.js
的内容; - return new Worker(代码如下)
/***/ "./src/model/run.worker.js":
/*!*********************************!*\
!*** ./src/model/run.worker.js ***!
\*********************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony default export */ __webpack_exports__["default"] = (function() {
return new Worker(__webpack_require__.p + "static/js/bundle.worker.js");
});
oneof
是作为rule
一个字段,oneof
只使用第一个匹配规则;
file-loader
将文件变成公共URL
- tapable思想、原理分析?
- 通过
synchook
继承了hook
,synchook
的代码是由hookCodeFactroy
模块创建的? hookCodeFactroy
通过new Function
方式创建函数, 函数体是有this.content方法生成;
- 通过
- webpack5的特性?
- sass-loader
webpack
将content
传给sass-loader
,sass-loader
将content
传给dart-sass
进行处理;dart-sass
处理完成后,再通过异步callback方式进行回传;
- webpack热更新原理是什么?
- 热更新功能是只更新修改过的模块,其他模块不更新。
- 是服务端和客户端通过websocket建立长连接,然后将更新文件的进行替换;
- 怎么做到的?怎么定位改的是哪个文件?如何将更新的文件推给客户端?如何将更新文件进行运行?
- webpack plugin和loader的区别是什么?
- loader是用于加载文件,plugin由于处理文件;
- loader主要是接入第三方应用,比如sass-loader、less-loader,将文件暴露给第三方应用进行处理;
- plugin主要是最内部代码进行处理;
- plugin
- 执行流程
- loader
- 执行流程
- webpack打包流程是什么?
- 初始化参数:从配置文件获取各个参数;
- 开始编译: 初始化compiler对象,加载所有配置插件;
- 确定入口: 分析入口文件,以入口文件为根目录自上而下分析出文件所有依赖;
- 编译模块: 使用loader对文件进行加载处理,获取模块之间依赖关系并保存起来;
- 完成编译:处理完文件后会异步在处理依赖的文件;
- 输出资源: 根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
- 输出完成: 根据hook路径输出文件;
- Hooks
- 设计优势
- 分治
- 隔离
- 拓展
- 设计优势
-
React思想有哪些?(0)
- 编程思想
- 声明式;
- 声明式是什么?声明式表现是一种映射关系,而不是具体的动作内容;
- 数据单向绑定;
- 分治
- 组件化
- 问题
- 父组件更新会导致子组件的更新
- 问题
- 组件化
- 数据驱动UI
- 数据单向流;
- 声明式;
- 设计思想
- Hooks
- 代理模式
- state: 状态机
- 编程思想
-
React是如何知道数据发生变化?(2)
- 组件内
- 通过setState方式
- 组件之间
- 通过Props
- 组件内
-
组件
- 组件类型
- HOC(高阶组件)和容器组件对比?
- 相似点:都是通过分解方式达到代码逻辑复用和逻辑简单;
- 不同
- 目的不同:HOC组件主要是解决相似组件代码逻辑复用的问题,容器组件主要目的是通过业务逻辑和UI组件分离,提高UI组件复用;
- HOC(高阶组件)和容器组件对比?
- 组件间传值
- 传值类型
- Props
- 传值
- 传组件
- Redux
- Context
- Props
- Context和Props使用场景的区别?
- 组件树各个层次使用公共数据时;
- Props适合单个数据从上而下使用;
- 传值类型
- 组件类型
-
Virtual DOM Diff原理
- Virtual DOM节点是如何生成的?
- 如果在JSX文件中,通过JSX层级关系就可以生成虚拟DOM;
- 通过遍历树的方式,将DOM节点变成虚拟DOM;
- 第一次渲染的时候,Virual DOM通过dom字符串生成dom节点;
- Virtual DOM和真实DOM之前的映射关系是什么?(3)
- 当数据更新时,Virtual DOM维护两份DOM副本,通过两个副本的diff找到修改点;
- 定位到修改点后,通过DOM节点的层级关系找到对应的节点; 如果是同一个层级的for循环的话需要增加key参数,从而帮助算法定位dom;
- Virtual DOM的diff算法?
- 一层一层往下找,如果父节点修改了则子节点则全部更新;
- 如何比较?比较标签类型、标签内容是否一致;
- Virtual DOM是在每个组件中还是只有一个?
- Virtual DOM存在react-dom中还是react中?
- 如果对两棵树进行diff?
- Virtual DOM节点是如何生成的?
-
React服务端渲染原理 (4)
- 执行react代码获得虚拟dom, 通过react-dom API将虚拟dom转成字符串;
-
React setState
- setState参量类型:对象和函数的区别?(5)
- 函数的方式可以保证state是最新状态;
- setState如何实现异步?(6)
- 将state变化保存队列中;
- setState如何修改值的?(7)
- setState参量类型:对象和函数的区别?(5)
-
React生命周期
- 它的作用是什么?(8)
- 通知目前组件的状态是什么?
- 通过hooks将代码进行分类
- 它的优缺点?(9)
- 优点是逻辑清楚,大家可以把对应代码放在对应的生命周期中;
- 缺点是割裂一些代码逻辑,导致重复代码的出现;
- 它的作用是什么?(8)
-
我对react有哪些理解(10)
React
关于DOM层操作的框架React
通过声明方式将数据和DOM节点进行映射,这个区别于jquery
命令式方案;- 当完成映射后下一步需要解决是数据管理问题,react主要通过
setState
方法进行状态管理; - 当数据生发变化,
react
通过虚拟DOM方式完成DOM更新; - 当有多个组件时候,通过
props
方式进行数据源绑定;
-
React底层原理
- Fiber Tree 和 Commit Phase
- Fiber Tree: 将tree进行拆解多个tree进行异步操作,在requestIdleCallback方式进行调用,
- Fiber Tree完成DOM节点生成、DOM节点之间引用关系、这步操作对dom结构没有影响;
- Fiber Tree另一个优势面对瞬间多次render的情况下,可以将让之前的Fiber Tree进程作废,从而可以最最新一次render做出相应;
- Commit Phase: 将fiber tree被执行完毕后,commit阶段使用递归的方式同步执行;
- 这个步骤不能异步:因为直接对DOM节点进行操作,如果异步的话会出现无法diff等问题;
- 16.0版本Fiber Commit Phase和之前的递归渲染有什么优势?
- 从执行次数:将渲染步骤拆成两个步骤(Fiber Tree 和 Commit Phase)面对多次render情况下有优势,不用等待之前render结束;
- 从执行数量级: 对大的tree渲染不会卡顿;
- 问题:
- 如果让一个递归从同步变成异步:如果是线性数据保存数据的上下关系,如果是树状结构则保存上下左右关系,这样可以保证从任何一个单个数据点能找到所有其他数据源;
- Fiber Tree: 将tree进行拆解多个tree进行异步操作,在requestIdleCallback方式进行调用,
- reconciliation(对账)
- 首先将之前fiber tree记录下来, 接着将将当前tree节点和之前tree进行对比(主要有三种方式update, replace和delete),最后在commit阶段对每个节点进行单独操作;
- 其他问题?
- 删除节点的子节点是否还要进行对比?不进行对比;
- Function Component(组件)
- 解决什么问题:如何进行组件化?组件之间如何进行逻辑隔离?Fiber Tree在组件化如何实现?
- 如果是我的话怎么做?使用类的方式fiber Tree数据隔离起来,其他的render方法等可以使用公用的;
- Hook
- Fiber Tree 和 Commit Phase
-
React16.0新特性
- 生命周期更新:
- 老的生命周期
- 初始化 getDefaultProps、 componentWillMount、componentDidMount
- 更新 componentWillUpdate、componentDidUpdate、componentWillReciveProps、componentShouldUpdate
- 卸载 componentWillUnmount
- 新的生命周期:
- 初始化: constuctor、componentDidMount
- 更新: getDerivedStateFromProps、shouldComponentUpdate、getSnapshotBeforeUpdate、componentDidUpdate
- 卸载: componentWillUnmount
- getDerivedStateFromProps(state, props):
- 在render之前都会调用,同时在初始化、更新都会调用;
- 这个方法应该返回一个对象来更新state,如果返回null则不更新;
- getSnapshotBeforeUpdate(prevProps, prevState)
- 在commit phase之前执行这个方法,用户获取DOM变化之前的信息;
- 错误相关的生命周期
- getDerivedStateFromError
- componentDidCatch
- 三个will前缀的生命周期都被设置成unsafe, 原理是fiber tree的异步化;
- 老的生命周期
- 组件
- Component类型
- 样式组件: 没有state和生命周期,只有render出来dom节点;
- 普通组件: 有state、生命周期、组件内部逻辑
- purecomponent: shouldComponentUpdate采取是浅比较的方式;
- 高阶组件: 类似于高阶函数方式,函数内部放入可复用的逻辑;
- 数据通信
- 通信方式
- 使用props在组件间传递
- 使用redux状态管理功能进行传递
- context方式
- 使用组件传递: 将需要用于数据的组件放在最一层,然后一层层传下去
- 事件订阅
- context
- react.createContext(defaultValue): 创建context;
- : 暴露具体的值
- displayName
- 通信方式
- Component类型
- react event
- 如何在DOM节点上绑定事件?
- 箭头函数
- 使用bind方式
- 如何在DOM节点上绑定事件?
- SSR
- react性能优化有哪些方法?
- setTimeout、setInterval等时间器要在componentWillUnMount中销毁;
- 使用shouldComponentUpdate来做性能优化;
- 使用异步组件、动态加载组件;
- 使用Immutable.js
- 生命周期更新:
- 浏览器渲染?
- 流程
- 解析HTML转换成DOM树
- 将字节码转成HTML字符串;
- 令牌化转换成HTML标签;
- HTML标签转成DOM数;
- 解析CSS文件转换为CSS规则树;
- 和HTML类似;
- 将DOM树和CSS规则树合在一起形成渲染树;
- 布局
- 通过盒模型递归方式从子节点开始计算大小,一直算到根节点;
- 渲染
- RenderLayer tree;
- 渲染方式
- 绘制: paint、栅格化;
- 合成: 将多个Render Layer合在一起;
- 解析HTML转换成DOM树
- 数据流程
- DOM Tree -> Render object -> Render Layer -> Graphics Layer
- 渲染
- layout -> paint -> composite
- 流程
- JS垃圾回收原理
- 执行标记
- 引用计数(循环引用)
- 阻塞
- 回流和重绘
- 内存泄漏
- 概念
- 性能监控
-
new 关键词
- new做了哪些事情:
- 执行初始函数,创建一个实例并将作用域指向实例本身;
- 将实例的
__proto__
属性指向函数的prototype
;
- new做了哪些事情:
-
Promise
- 方法
- Promise.all
- Promise.allsettled
- Promise.race
- Promise.reject
- Promise.resolve
- promise.then(f1, f2)和promise.then(f1).catch(f2)区别
- 就近原则;
- catch可以捕获到then中错误逻辑;
- 时序
- 嵌套
- 方法
-
箭头函数?
- 箭头函数和function区别
- 函数头
- 没有
function
关键词,只能通过函数表达式或者匿名函数的方式创建,无法通过函数声明的方式来表达;
- 没有
- 函数参数
- 当单参数省略括号;
- arguments: 没有arguments;
- 函数体
- this: 本身没有this,继承所在作用域链上层的this(为什么?猜测);
- 当单行逻辑时省略大括号;
- 不能当做构造函数
- 函数头
- 箭头函数和function区别
-
Object.Proxy
-
Function
- 函数提升:
- 方法
- bind: 绑定一个绑定指定上下文的函数,同时可以传入预先参数;
- Object.prototype.isPrototypeOf和instanceOf的区别?
-
Array
- slice和splice区别?
- 参数:slice是两个参数、splice三个参数
- 功能:slice具有删除/分割/,splice具有增删改功能;
- 返回值:返回被操作的值、被操作下来的值;
- 对原值是否修改:对原数组没有影响,有影响
- slice和splice区别?
-
循环和迭代
- 相同点: 重复做一些相同的事情;
- 不同点:循环一般需要设置开始和结束条件,但是迭代不需要设置条件;
-
原型链
- 关于原型、实例和构造函数
prototype
是函数指向它的原型,默认是一个对象,对象包含constructor、__proto__
;__proto__
是一个指针,用于实例指向构造函数原型;prototype和__proto__的区别
prototype
是属性而__proto__
则是o指针;prototype
只能用于函数,__proto__
可以用于对象和函数;prototype
可以直接编辑,__proto__
则不可以;
- 怎么修改一个实例
prototype
:Object.setPrototypeof方法
; - 构造函数的原型是
Object原型
的实例,A.prototype.__proto__ == Object.prototype
; instanceof
用于判断一个变量是否是一个构造函数的实例, 判断的原理是判断实例的__proto__
和构造函数的prototype
是否相等,或者通过Object.prototype.isPrototype()
来判断;
- 关于原型、实例和构造函数
-
作用域链
- 问题
- 从作用域链关系来看实例和构造函数之间关系?
- 问题
-
基础知识
- throw: 抛出一个用户自定义的错误,后面代码(函数或者代码块行)将不执行,而是调用调用栈最近的一个catch,如果没有catch的话则则程序直接退出;
- 多个throw在一起的情况
- 多个try/catch的情况
- throw抛出的数据类型有哪些? 任何类型的数据
- 事件循环
- 字面量
- 调用栈(Call Stack): 将执行的函数放入堆栈中,如果执行函数还调用其他函数则其他函数也放入栈中,当函数执行完成后则从栈中删除;
- 调用栈原则是先进后出;
- 调用栈没有空间限制,如果超出则会报出堆栈错误;
- 操作符
- 一元操作符
- 位操作符
- 加性操作符
- 乘性操作符
- 布尔操作符
- 关系操作符:
- 字符串之前比较字符编码值,大写的编码值小于小写字母;从首字母进行比较;
- 一个是数字、另一个是字符串,则将字符串转成数字进行比较;
- 逻辑操作符
- 条件操作符
- 赋值操作符
- 逗号操作符
- 数据类型对比
==
和===
的区别:==
(相等)不转换类型进行对比,===
(全等)转换类型进行对比;- 转换类型的原则是:
- 如果有布尔值则先转成0或者1;
- 如果比较的一方是数字另一方是字符串,比较之前先将字符串转成数字;
- 如果一方是
Object
另一方不是,比较之前先调用valueOf
转换成基本类型,如果换成基本类型失败的话则使用toString
; - 如果两方都是
Object
则比较是不是同一个对象; undefined
和null
在==
情况下为true;underfined
和null
不转换成其他类型;NaN
和任何值都不相等包括它自己(NaN
==NaN
为false
);Infinity
和-Infinity
和其他值相比都是false,但是和自己相比则为true
;
null
、undefined
、NaN
、{}
、[]
等特殊类型如何转换类型?null
、undefined
不转换类型;NaN
{}
- 为什么
[]
在if([])
和[]==""
两种情况下,表现不一致?
valueOf
和toString
两个APIvalueOf
:
ToPrimitive
、ToNumber
、IsFalsy
方法是什么?Object ToPrimitive
是先调用哪个方法?toString
还是valueOf
?(一般都会toString(), 因为valueOf方法返回值不是基础类型)ToNumber
:
- 运算符
- 算术
- 幂(**):
3**2
- 累加(++):
++x
在累加之后返回值,x++
在累加之前返回值; - 一元加号和减号:
+"a"
转成数据类型,如果不是数据类型则尝试转成数据类型,+undefined //NaN
、+null //0
;
- 幂(**):
- 赋值
=
: 将右边值赋值给左边;x = y= 10 转化为 y = 10 x = (y = 10)的返回值
- 逗号
- 解构赋值:将对象属性/值和数组的值赋给多个变量,赋值的原理和=赋值一 数组和对象的区别是:数组按顺序进行赋值,对象按属性名进行赋值, 一个用[], 一个用大括号;
-
主要的形式:
var [a, b] = [1, 2, 3]; a = 1; b = 2;
-
赋值增加默认值:
var [a=5, b=7] = ["a"]; // a: "a"; b: 7
; -
拓展运算符将剩余值赋值:
var [a, ...b] = [1, 2, 3] // a: 1, b: [2, 3]
; -
忽略默认值
var [, b] = [1, 2]; b= 2
-
数组嵌套赋值: 通过[]进行嵌套赋值;
-
通过函数返回值赋值:
var [a, ...b] = fn() //
; -
对象属性赋值:
var {a, b} = {a: 1, b: 2}; // a:1 b:2
-
对象赋值增加默认值:
var {a=2, b} = {b: 2}; // a:2 b:2
-
修改变量名称:
var {a:a1, b:b1} = {a: 1, b: 2}; // a:1 b:2
-
拓展运算符将剩余值赋值:
var {a=2, ...b} = {a: 1, b: 2, c: 2}; // a:1 b:{b:2, c:2}
-
修改名称和增加默认值:
var {a:a1=2, b:b1} = {a: 1, b: 2}; // a:1 b:2
-
函数参数上增加默认值:
-
对象嵌套解构:
var {a:{c}} = {a: {c: 1}};
; -
在for/of、each、map中使用;
-
变量的互换:
[a, b] = [b, a]
-
可以获得原型链的上属性名;
-
- 算术
- 表达式
- for/of: 在一个可迭代的对象中创造一个迭代循环,可以自定义迭代钩子;
- 和for/in的区别:
- 可以使用对象不一样:
for/in
可以用于object
而for/of
不能用于object
, 因为object
不是一个可迭代对象; - 遍历属性范围不一样:
for/in
是任意顺序遍历一个对象的除symbol
以外可以枚举的属性、for/of
则用于遍历对象的可迭代的属性;
- 可以使用对象不一样:
- 和for/in的区别:
- for/of: 在一个可迭代的对象中创造一个迭代循环,可以自定义迭代钩子;
- 运算符优先级
- ES6对象
- 简写的方式:
var a = 0, b = 1, c = 2; var obj = {a, b, c}
; - 可计算属性值:
var param = 2; var obj = {param: 22}
; - 可使用展开语法命名属性
- 简写的方式:
- 展开语法: 当函数调用和数组构造时,可以用展开语法对数组和字符串进行展开,当对象进行构造时,可以对对象进行展开;
- this
- 指向当前执行环境,执行环境里面包含作用域、变量等;
- 在常见几种情况下
- 几种函数中
- 函数声明:
- 匿名函数: 作为对象方法
this
指向对象本身、其他情况指向上一层的执行环境; - 构造函数:
this
指向实例本身; - 箭头函数:
this
继承作用域上一层的this
;
- 对象
- 匿名函数
this
指向对象本身; - 箭头函数
this
指向对象外部执行环境;
- 匿名函数
- 原型链
this
指向实例所在的执行环境,从而this
调用的方法会从原型链上寻找;
- 作用域链
this
执行当前作用域,如果当前作用域没有对应的属性则返回undefine
;
- 事件
- 内联绑定\on事件+匿名函数\addEventListener方式绑定方法和函数,
this
指向dom本身
- 内联绑定\on事件+匿名函数\addEventListener方式绑定方法和函数,
- 几种函数中
- 严格模式
- 将过失转化成错误;
- 简化变量
- 更加安全
- 执行环境
- typeof
- 模拟typeof: 是否变量的
__proto__
和各个对象prototype
是否相等;
- 模拟typeof: 是否变量的
- instanceof
- 判断实例的
__proto__
和构造函数的是否具有同一个prototype。如何实现: 使用getPrototypeOf、__proto__
- 判断实例的
- generator/yield:
- 通过
function *
来实现generator
方法; - yield:
- 通过
- async/await
- await只能在async函数中运行,await会阻塞async函数体下面逻辑的运行;
- class
- 静态方法:
static method
只能在实例中调用,不能在内部调用;
- 静态方法:
- throw: 抛出一个用户自定义的错误,后面代码(函数或者代码块行)将不执行,而是调用调用栈最近的一个catch,如果没有catch的话则则程序直接退出;
request
get / http1.0
host: xxx.com
expires: new Date()
response
200 ok
- HTTP报文
- HTTP格式
- request报文由四个部分组成: 起始行、header、空行、body;
- 起始行: 协议、路径、方法;
- response报文也有四个部分组成: 状态行、header、空行、body;
- response: 协议、状态码、返回值;
- 优点
- 拓展性强
- HTTP方法
- 列表
- GET
- POST
- HEAD
- PUT
- DELETE
- CONNECT
- OPTION
- TRACE
- PATCH
- 幂等
GET
HEAD
DELETE
PUT
- 可缓存
- 安全
- 列表
- HTTP请求头部
- general header: request header和request header都会有
- request header: 请求头
- response header: 响应头
- entity header: 实体头
- HTTP常见header字段
- accept: 客户端告诉服务端支持哪些文件类型 filetype;q,filetype;q;
- filetype: 文件类型 比如text/html
- q: 权限因子;
- content-type: entity header 表明实体的mime值 mime-type charset boundary;
- expire/cache-control: 响应头/通用头,权值比expire大;
- etag/if-match/if-none-match: etag是服务器下发, if-none-match/if-match是客户端上传代表相反的意思;
- last-modified/last-modified-since/last-unmodified-since: last-modified是服务器下发,last-modified-since/last-unmodified-since是客户端上传代表意思相反;
- accept-encoding/content-encoding:
- vary:
- accept: 客户端告诉服务端支持哪些文件类型 filetype;q,filetype;q;
- request报文由四个部分组成: 起始行、header、空行、body;
- HTTP格式
- HTTP缓存
- 字段列表
- expires: 设置过期时间;
- cache-control: 控制缓存;
- 应用范围: public/private
- 设置: no-cache
- 设置过期时间: max-age
- last-modified: 服务端下发文件最后修改时间;
- last-modified-since: 推测是客户端发送文件最后修改时间,服务器根据这个时间点判断是下发实体内容还是304;
- if-none-match: 客户端发送
etag-value
字段,服务器判断是否有对应etag值判断; - eTag: 强校验的方式,校验的逻辑和文件内容相关;
- vary: 一种和user-agent相关的校验方式,比如用在移动端和PC端,可以让cache知道当前是哪种设备,应该使用哪个文件;
- 缓存流程
- 浏览器请求一个资源会先在浏览器缓存中进行判断,判断主要分为两个阶段(强制缓存阶段和协商缓存阶段)
- 在强制缓存阶段主要判断两个字段(expires和cache-control),如果资源没有过期则直接使用相关资源且流程结束;
- 反之则进入协商缓存阶段,这个阶段主要有两个步骤:if-none-match和last-modified;
- 第一步if-none-match发送etag-value进行文件内容判断,服务器会返回304或者新的实例;
- 或者服务器不支持etag的话则使用时间判断,通过
last-modified-since
字段发送文件修改时间,服务器会根据时间返回304或者文件实例;
- 缓存类型
- 权限划分: 公有和私有
- 存储位置划分:内存和硬盘
- 技术
- 新鲜度:衡量文件是否过期的指标;
- 驱逐算法: 一种清除浏览器文件缓存的算法;
- revving技术: 给文件设置版本号可以重新请求新的文件;
- 缓存时间计算公式: cacheTime = responseTime + expireTime - currentTime;
- 字段列表
- Cookie
- set-cookie:服务器端设置cookie;
- httponly: 阻止js读取cookie;
- security: 安全性;
- 解决xss注入的问题
- 对输入值进行转义;
- 解决CSRF跨站请求伪造(cross-site request forge)
- CSRF: 通过获取用户Cookie信息,模拟请求发给服务器;
- 解决方法:
- httponly: js无法获取cookie;
- sameSite:
- none: 可以在相同站点或者跨站上发送cookie;
- strict: 只能在相同的站点下发送cookie;
- lex
- 后端请求判断用户的
- referer: 显示从哪个入口发出的请求;
- set-cookie:服务器端设置cookie;
- HTTP CORS(Cross-Origin Resource Share)
-
CORS的使用场景
- 字体
- WebGL贴图
- Canvas载入图片
- ajax请求
- 子域名之间的数据请求;
- 子域名之间共用一些Cookie数据;
-
CORS如何开启:
-
CORS工作流程
- 预检请求
- 浏览器通过option方法发送
CORS
相关字段请求; - 服务器通过响应头返回被允许的字段;
- 浏览器会根据响应头判断是否支持
CORS
;
- 浏览器通过option方法发送
- 预检请求
-
通过设置cross-allow-origin字段;
- 响应头
- Access-Control-Allow-Origin
- Access-Control-Allow-Method
- Access-Control-Allow-Method
- Access-Control-Expose-Header
- Access-Control-Max-Age
- 请求头
- Access-Control-Request-Method
- Access-Control-Request-Header
- Orign
- 响应头
-
- HTTP各个版本介绍(1)
- HTTP各个版本
- HTTP 0.9: 单行请求、没有http头;
- HTTP 1.0: 增加http头、状态码
- HTTP 1.1: 增加tcp连接共用(长连接),并发请求、缓存机制、协商缓存;
- HTTP 2.0: 二进制、请求合并等;
- HTTP各个版本区别
- HTTP 1.0相比HTTP 0.9拥有请求头,显得更加完整,同时确定之后版本的整体结构;
- HTTP 1.1相比HTTP 1.0在性能方面得到很大的加强;
- HTTP 2.0相比HTTP1.1在性能完成又一次飞跃;
- HTTP发展路程
- 伟大产品的第一个版本可能是简陋的;
- HTTP各个版本
- HTTP2帧和流的概念(3)
- HTTP2创建帧和stream概念:帧分为请求帧和数据帧两种类型,多个帧组成流;
- HTTP2如何发多个Header头:
- 用一个请求frame加载header,其他frame引用这个帧同时可以增加内容;
- HTTP2如何压缩Header头:
- 使用字典的方案:客户端和服务端共同维护一套字典,相同值直接传序号不用再重复换内容;
- 哈夫曼编码;
- HTTP2静态字典和动态字典区别?静态字典维护常见不变请求,动态字典维护变化的
- HTTP1.x的连接管理(4)
- HTTP1.x有哪些连接?短连接、长连接和连接流水线;
- 长连接维持tcp连接不断开,从而节省tcp握手的时间,提高连接的性能;(本质上还是一个串行请求)
- 连接流水线则将多个http请求放在一个TCP中;(本质是一个并行请求)
- HTTP1.x的连接流水线和HTTP2的请求有什么区别?
- 提高HTTP请求效率办法(5);
- 域名分片:浏览器对同一个域名有并发请求次数限制,可以通过域名分片提高并发数目;
- 使用http2请求;
- HTTP 重定向(9)
重定向是请求资源不在目标路径中,服务端返回其他路径,浏览器根据新的目标路径进行跳转;
重定向类型;
- 永久重定向: 目标文件被永久移到其他路径中;
- 301:
- 308: 覆盖非GET请求;
- 临时重定向:
- 302:
- 303:
- 307: 覆盖非GET请求;
- 选择重定向:
- 300: 使用缓存;
- 304: 未修改 重定向死循环: 报服务器错误;
- 永久重定向: 目标文件被永久移到其他路径中;
- HTTP 内容协商
- content-type/accept:
- HTTP 条件请求
- 浏览器发送一些条件性字段,比如if-match/if-modified-since等,服务器判断字段并返回相应的内容;
- 常见场景:
- 判断文件是否缓存
- CMS或者Wiki等提交内容前判断,通过if-match/etag
- 多点的情况下会出现一种竞态条件,提交时需要通过if-match做一个提前判断
- 大文件断点续传,通过range字段实现
- range:
- HTTP 认证
- HTTP数据压缩
- HTTP2 2进制压缩;
- 选择器
- 属性
- 布局
- 盒模型
- css3如何做个三角形?
- css3边框可以组成一个正方形,每个边框其实一个就是一个三角形;
- css单位
- fr/vh|vw
- fr: 是grid布局一个单位,主要用于grid-template-columns;
- vh/vw: 视图高度和宽度
- flex
- flex = flex-grow/flex-shinke/
-
常见方法
- 动态规划: 一个问题可以解决成多个子问题,子问题之间不是相互独立,而是相互影响的;
- 贪心
- 分治法
- 回溯
- 分支界定
- 双指针法
-
常见功能
- 查找
- 排序
- 去重
-
Promise
多个then/catch的调用关系(0)
promise
可以绑定多个then/catch函数、同时能在赋值变量上继续绑定then;
多个then
按照then
绑定的顺序执行;
then
不会在本轮事件循环中执行
var promise1 = new promise(()=>{
....
}).then(()=>{
});
//继续绑定then
promise1.then(()=>{});
多个Promise相互嵌套的调用关系(1)
多个then和多个Promise相互嵌套执行顺序(2)
promise.all等方法如何使用(3)
异步函数嵌套地狱怎么解决?(4)
2020-06-22
* const、var、let区别
- 对象重复属性名;
2020-6-20
1,2,3,4,
- Number转成String: toString()、+ '', String();
- String转成Number: 六种方式;
- Boolean转成Number: +true/false、Number()
- Number/String转Boolean: !!, Boolean()
null
: 表示缺失标示,对象没有设置(本质上是空对象指针);undefined
: 表示变量没有被定义;falsy
: 虚值,表示在Boolean表达式中为false,有7中情况NaN
: 表示不是一个数字;Infinity
: 表示数字无限大;
- rem:
- em
- px
2020-6-19
Cookie设计中有个特点:
- http请求时会带上Cookie信息(这个为客户端模拟请求创造了条件)
- 同源策略下可以读取Cookie;
阻止Cookie被读取的方式:
- 使用同源策略阻止Cookie被读取;
- 使用HttpOnly的方式;(服务器端设置)
HTTP提交Cookie的两个条件
- 同源策略
- 相同路径或者父路径;
__proto__
是一个访问属性,用于访问对象内部属性;
构造函数的实例的__proto__
指向的构造函数的作用域;
通过字面量生成的变量的__proto__
是什么?
通过var a = "111'
和 var a = new String("111")
的区别是什么? 一个字符串、一个是对象;
String
既可以做对象、函数和构造函数;
viewport、media query、rem
- 直接绑定在DOM上,比如onClick;
- 通过js进行绑定;
- 通过addEventListen进行绑定;
ES6 Module
: 是ES6采用模块化标准, 主要import
和exports
为关键词来进行输入输出;
AMD
: 异步化模块引用方案, 主要代表是require.js; 主要通过define、require.config, require来进行引用。当代码执行时异步化引用JS;
CMD
: AMD
的优化版本,不是一次性引入所有文件,而是在使用过程中引用;
Common
: 是Node.js
使用一套方案,主要用require、modules、exports等关键词;
import
常用于编译时调用(必须放在页面头部代码逻辑之前),require
则可以运行时调用;import
具有多个功能比如as、单独导入、导入多个接口等;import
获取是值引用,require
获得是值拷贝;
2020-06-18
数组相关方法:
增:push、concat
删:pop、splice,slice
改: reverse、flat、
查: filter、reduce、reduceRight、includes、indexOf、every、map、forEach、some
其他:join,toString
循环: filter、reduce、reduceRight、includes、indexOf、every、map、forEach、some
不循环:
增加删除: pop、push、splice、slice、
连接:concat、
修改:reverse、flat
哪些方法可以改变之前数组:push、concat、reverse、splice、sort
哪些方法不改变之前数组: slice、forEach、map、filter、reduce、reduceRight、includes、indexOf、every、map、forEach
第零层: 是什么?(有哪些API) 第一层: 怎么用?(哪些场景下适用、在工作中使用) 第二层:怎么实现的? (源码中有哪些概念? 自己动手试着实现一下?) 第三层:怎么和小白说明白?(如何简洁表达出来) 第四层:有哪些地方有问题可以优化?()
最常见的API: setState(object, fn);
setState之前考虑是在频繁调用的时候不影响性能。那setState是异步还是同步?
如果是我自己设计的话,我会怎么设计?
- 我会采用类似防抖策略: 将setState方法都存在一个数组中,然后在一个时间段内集中处理;
- 集中处理的逻辑: 将setState参数都存在数组中,一次处理一个并将值传给下一个(还是合并?);
对于setTimeout的情况是什么? 不在批量处理的逻辑中;
// 收集
this.setState({
a: this.state.a + 1;
});
this.setState({
a: this.state.a + 1;
});
// 合并
[{
a: this.state.a + 1
},{
a: this.state.a + 1
}];
arr.map((obj)=>{
});
setTimeout、promise、react事件、原生事件、正常、匿名函数五种情况下,哪些是异步哪些是同步?
异步情况: react事件、正常、匿名函数(异步情况下,如果setState传参是对象的话会被合并并且不会实时展现出来);
同步情况:setTimeout、promise、原生事件;
解决方案:setState(updater, callback);
相关资料:真的了解react
2020-06-17
基本数据类型:string、number、boolean、null、undefined、symbol 引用数据类型:object
强制类型转换: toString等方法;
常见的状态码有哪些?
- 200:
- 301:
- 302:
- 304:
- 404:
- 501:
- 502:
常见的状态码开头
- 1* 继续操作
- 2*:请求成功;
- 200: 请求成功;
- 203:
- 204:
- 3*: 重定向;
- 300: 返回多个重定向地址;
- 301: 请求的内容永久被修改;
- 302: 请求的内容临时被修改;
- 303: 查看其他地址;
- 304: 未修改;
- 4*: 客户端错误;
- 400: 请求语法错误,服务端无法理解;
- 401: 要求用户身份验证;
- 403: forbidden
- 404: not find;
- 412:
- 5*: 服务端错误
- 500: 服务器内部出现错误;
- 501: 不支持请求功能;
- 502: 从网关或者代理服务器请求收到的相应无效;
- 503:
TCP协议和UDP协议的区别?
TCP是面向连接的,UDP不需要连接; TCP连接的三次握手: 主机A和主机B;
- 第一次握手:我要给你发数据;
- 第二次握手:好的,你什么时候发;
- 第三次握手:我现在就发
三次握手的目的:确认数据的请求和接收的同步;
http的缓存策略是什么,强制缓存和协商缓存?
缓存策略是尽量使用客户端缓存,这样的好处是提高应用性能和降低服务器压力;
强制缓存:
- expire:
- Cache-Control: 协商缓存:
- if-modified
- if-modified-since
http和https的区别?
跨域的方式?
- cors
- 代理(proxy)
- Iframe
- postmassage + iframe
- window.name + iframe
- JSOP
- websocket
同源策略? 同源是指: 协议 + 域名(子域 + 主域) + 端口 都要一致
XSS是什么,怎么防范?
XSS是跨站脚本攻击,对尖括号进行转义;
CSRF是什么,怎么防范? 跨站请求伪造,使用同源检测、cookie双重验证;
布局:
flex: 弹性布局
BFC: block formating context, 作用是将当前容器和其他容器隔离开,容器不会影响其他容器;
选择器: id >class(伪类)>标签
属性权值:内联 > id > class = 伪类 = 属性选择器 > 标签
普通
分组器
组合器
css3组合选择器:
- 子节点
>
: 获取子节点的元素;- 兄弟节点
+
: 获取紧邻的兄弟节点;~
: 获取之后所有兄弟节点;
伪类和伪元素的区别:
- 伪类:表达一种状态或者条件信息(比如按钮点击三态等等);
- 伪元素:表达一种没有被包含的实体;
- let相比var没有变量提升、不能重复定义;
使用DOMParser
或者使用createElement
和innerHTML
方式,先将字符串转换dom节点,然后将dom节点转换成object;
冒泡排序: 通过双层循环将每个元素和其他元素都做一次比较;
快速排序:通过一种分治的手段将数组分解成更小的数组,再将处理好的每个组件合并起来;
插入排序:打牌时候的摸牌逻辑,抓到一张牌和手上牌做比较,然后放大合适的位置;
选择排序:选择最大或者最小放在排序序列的尾部或者头部;
选择和插入的区别?
- 比较的对象不同:插入排序比较的对象是已排序的数组, 选择排序的比较对象是未排序的数组;
2020-06-15
时间复杂度:我的理解是一段代码运行需要时间长度;
空间复杂度:我的理解时一段代码运行时需要空间大小;
时间复杂度和空间复杂度不代表具体数值,而是代表一个趋势,是指数、还是对数等;
如果使用hashHistory
的话,则通过onhashchange
方式来触发,但是hashchange
的方式有几个劣势:
- 对搜索引擎不友好;
- 不能很好表达出层级关系;
- 提供的信息不够
hashchange
的优势:
- 简单
- 兼容性好
如果使用browserHistroy
的话,可以通过pushState
和replaceState
方式来改变url;
使用Link
组件可以进行push
和replace
操作,通过可以触发内置History
对象,当浏览器前进和后退则又可以触发popstate
事件,所以覆盖所有操作;
memoryHistory
则用于node
环境中;
- pushState可以传值和title,而location.href不能;
- pushState可以不通过hash改变URL同时页面不会刷新;
- pushState可以比location.href改变的内容更多, 比如pushState可以改hash也可以改url;
Node相比Web少了UI,所以没有UI排版等工作;
Node将异步分为六个阶段,每个阶段执行对应阶段的任务; Node有哪六个阶段?timer/IO/prepare/poll/check/close
2020-06-13
2020-06-12
是什么? new Map(): 通过二位数组创建对象; new Set(): 通过数组传入将数组中重复的数据 Symbol():
Set和Object的区别是什么?
- Set创建是可迭代的对象,从而可以使用
for of
; 但是通过Object
创建的对象则不是可迭代的对象; - Set创建对象没有value只有key,
Object
则既有value
也有key
;
Set和Array的区别是什么? 值得唯一性;
Set对象使用的场景有哪些?
Set对象的创建解决之前哪些问题?
WeakMap
Object.prototype.isPrototypeOf(target); Object.setPrototypeOf(target, source); Object.getPrototypeof(target, source);
分为三个部分:定义(c)、获取(g)、判断()
Object.defineProperties() Object.defineProperty()
获取自身属性的方法 Object.getOwnPropertyDescriptor() Object.getOwnPropertyName() Object.getOwnPropertySymbol();
Object.prototype.hasOwnProperty()
entries将对象转化为key/value的二位数组; fromEntries则是将二位数组转成对象;
is+形容词
: 比如freeze有动词名词功能但没有形容词, 因为is后面需要增加形容词,所以freeze改成frozen;- API设计是成组出现的, 覆盖的功能比较全;
对象拓展: Object.isExtensible Object.preventExtensions
对象冻结 Object.freeze Object.isFrozen
对象锁定seal Object.seal Object.isSealed
extension、freeze、seal之前的关系: freeze > seal > preventExtension 包含关系,freeze最严格、seal次之、preventExtension最弱;
数据描述符和存储描述符不能放在一起使用;
configurable
: 官方描述configurable
属性为false是属性描述符不能被修改(意思是不能为二次定义)和删除(意思是不能使用delete方式), 当configurable
为true的时候则可以被修改和删除。使用场景常量类型;
writable
: 表示属性是否可编辑,默认是false;
enumerable
: 表示可枚举,我理解可枚举的意思是for.in循环时候可以找到对应的属性值。默认是false不可枚举。使用场景是用于内部变量;
set
/get
: 当object
的被赋值和调用时,set
和get
方法就会被触发;
configurable
、writable
和enumerable
三个字段的关系:可删除、可写、可查找;
2020-06-11
2020-06-10
Object.create
只能在Object
下使用;
Object.prototype.create
可以再所有实例对象中使用;
这是一种编程设计技巧。
2020-06-09
tapable有哪些异步和同步处理函数?
2020-06-02
2020-06-01
2020-06-01
2020-06-01
$((master))
2020-06-01
yarn --ignore-engines
分解
- 样式
- 形状
- 颜色
- 方向
- 阴影
- 动画
- tranform
- translate
- rotate
- skew
- opacity
- duration
- tweening
- tranform
灯泡、叶子的形状如何画出?使用Bezier Curve曲线画出。 阴影如何画出?用bezier曲线画出区域,然后用黑色进行填充。 路径如何从起点到终点的动画展示?
path元素中M和C
两个关键词是什么意思?M代表直线,C代表贝塞尔曲线;
-
提纲
- User->Gitlab->Runner
- User->Gitlab(提交代码后gitlab如何知道)
- Gitlab->Runner (如何通信的 )
- Runner->Gitlab (如何返回结果的)
-
配色和文案
- 在箭头上写文字;
- 参考配色
- 内容准备
为什么使用类库?帮助实现一些简单功能 选择svg和canvas一起还是组合的?svg和canvas每个单独选个库,这样后面方便切换,而且兼容性更好。
svg方面选择svg.js,原因是svg.js是函数式编程进行链式调用;
svg.js包含哪些内容:
- class
- mulitpaint(手动操作)
- animation
- animate
- runner
- timeline
- plugins
svg.js存在的问题无法生存动作节点,导出来都是静止的svg;
- 将dom转化成canvas的原理参考gif.js;
- 通过addFrame方法增加节点;
- 最后将节点输出;
给blob
生成url地址,通过<a>
标签进行下载,<a>
标签能下载的前提是有downloadName
属性
URL.createObjectURL(blob);
- 获取dom节点类型,使用对照表比如
div
转换rect
,找到对应的元素。 - 获取节点的样式类型,再使用
canvas stroke
和fill
进行转化; - 最后再通过canvas
toDataBlob
toDataImage
两个方法进行输出;
xmlns: xmlnd命名空间,我理解是用不同解析器进行解析;
2020-05-26
2020-05-26
通过使用@keyframes关键词设置动画;
animation
属性有多个子属性:
animation-name
: 设置动画的名称animation-duration
: 设置动画持续时间;animation-delay
: 设置动画持续时间;animation-fall
?
用到几个属性值:transform, transform-origin,
css坐标系和迪科尔坐标系旋转方向是相反的; css坐标系以逆时针旋转的;
transform: rotate旋转;
transform-origin 设置旋转的原点;
<div class="line" style="top: 75px; left: 100px; width: 0px;"></div>
.line::after, .line::before{
content: " ";
display: block;
position: absolute;
top: 0px;
right: -16px;
height: 2px;
width: 16px;
background: #F9F6F7;
transform-origin: 0% 50%;
}
.line::after {
transform: rotate(205deg);
}
.line::before {
transform: rotate(155deg);
}
2020-05-25
这两个伪类需要增加content属性才能有作用。比如content:" "
2020-05-25
2020-05-20
2020-05-20
cjs
Announcing a new --experimental-modules
rollup不会自动对import做转换。
如果node不支持import的话,就会报错;
2020-05-18
使用React Hook可以在函数内使用React state和自动render等功能。
它的好处有几点:
- 打破了Class类的限制,函数相比于Class类显得更加简洁和灵活;
- 对于组件之间共用状态的场景,用函数更加方便;
使用React Hook写出的代码更加可预测.
什么是语法提案?
组件预编译?
component folding?
react的精神原则?
响应式编程?
2020-05-15
分别用了cache、artifacts、将node_modules移到上一层目录、npm ci
、yarn install --frozen-locefile
等方式来解决这个问题;
cache: 为下一个pipeline缓存一些文件; artifacts: 是将一个job的资源传递给下一个;
在node_modules文件很大的情况下,上面两种方案node_modules加载的时间比npm install还要长.....
将node_modules移到上一层目录的方案需要处理很多情况,很容易出错;
最终选择npm ci
和yarn install --frozen-locefile
两种方式,npm ci
省去了查找和压缩树等步骤从而比npm i
快一倍以上;
2020-05-15
- 无法保证node_modules是最新版本;
- runner是公用,所以要保持环境的干净;
2020-05-15
可能有两种情况导致
- 没有登录,使用
npm login
进行登录后再操作 register
注册源被修改,使用npm config set register value
进行修改
2020-05-14
使用__dirname
可以获取文件所在的文件夹绝对路径;
__filename
可以获取文件绝对路径;
process.cwd()
可以获取调用时所在路径;
2020-05-14
在相同的repository
和相同的branch
发起git commit api,特别是这个文件还没有被提交;
shell
的<
小于号表示一个输入重定向; 对应 >
大于号表示输出重定向;
所谓输入重定向是指:内容输入不是从键盘输入,而是从文件输入; 所谓输出重定向是指:内容不是输出到屏幕中,而是输出到文件中;
今天再用curl
提交时用到这个方法:
curl --request post https://**********
--form "content=</lib/commit.sh"
content字段值是commit.sh文件的内容;
2020-05-14
使用gitlab api来实现这个功能,对应接口
通过curl方式来调用这个接口,需要注意的下面几点:
- 需要提交每个文件的信息不能提交一个文件夹;
- 不能在当前分支去提交,会导致
Branch diverged
错误;
2020-05-14
- 读取
package.json
文件dependencies
和devDependencies
属性值; - 将
dependencies
和devDenpendencies
属性值中每个模块作为根节点; - 找到每个根节点依赖的所有节点,并生成依赖树;
- 寻找依赖树中相同的模块,判断是否可以兼容, 如果可以兼容则压平依赖树(请求register服务);
- 将模块下载到./npm目录中,通过版本号进行管理;
- 最后从./npm中解压到本地node_modules文件夹中;
2020-05-14
npm cache
npm offline等等
NODE_PATH
2020-05-14
yum
是linux上一个包管理工具。通过命令行的方式运行,用法很像npm
。
2020-05-14
chcp
是windows改变cmd代码页(字符编码)的命令;
chcp
显示当前代码页
chcp xxx
设置代码页;
2020-05-14
yarn install --frozne-lock
方法
2020-05-14
node-sass
模块难安装是出了名,加上测试机没有翻墙功能导致npm install卡死。
npm
有一个配置文件叫.npmrc
,在执行npm
命令时候会使用.npmrc
里面的配置。
通过npm config set key value
方式来设置配置,配置设置成功可以通过 npm config ls -l
来展示;
我们通过设置镜像地址和node-sass地址来解决卡死的问题
npm config set registry https://registry.npm.taobao.org
npm config set phantomjs_cdnurl https://npm.taobao.org/dist/phantomjs
npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
2020-5-13
webpack
的sass-loader
默认使用node-sass
作为sass编译模块的。
通过sass-loader
在options中暴露一个字段impentions
用来使用其他sass编译模块, 配置如下
{
type: sass-loader
options: {
implementation: require("sass") //require("dart-sass")
}
}
2020-5-13
当一行脚本很长时,可以使用反斜杠\
来分割脚本,注意是\
后面不能有空格(我理解是多的空格会导致shell编译器分割错误)
curl --request POST "${HOST}${CI_PROJECT_ID}/merge_requests" \
--header PRIVATE-TOKEN:${GITLAB_PRIVATE_TOKEN} \
--form id=${CI_PROJECT_ID} \
--form title=${CI_COMMIT_REF_NAME} \
--form source_branch=${CI_COMMIT_REF_NAME} \
--form target_branch=${TARGET_BRANCH};
2020-05-13
错误代码如下
variable:
PROJECT_NAME: demo
job1:
stage: build
script:
- ../${PROJECT_NAME}/node_modules/.bin/jest
当runner执行job1时,会出现
../${PROJECT_NAME}/node_modules/.bin/jest 路径不存在
按理说应该会解析成:
../demo/node_modules/.bin/jest
2020-5-12
gitlab v11
版本中存在job执行顺序问题: 没法实现一个自动任务在一个手动任务运行之后自动执行?
gitlab v11
默认逻辑: 一次把所有自动化任务都执行完;
2020-5-12
2020-5-12