AES加密算法 CSC模式:通过密钥和salt(起扰乱作用)按固定算法(md5)产生key和iv。然后用key和iv(初始向量,加密第一块明文)加密(明文)和解密(密文)。
加密
对称加密 Symmetric Encryption
共享密钥加密 私钥加密算法。加密和解密时使用相同密钥,或是使用两个可以简单相互推算的密钥。事实上,这组密钥成为双方或多个成员之间的共同秘密,以便维持专属的通讯联系。
要求雙方取得相同的密鑰是對稱密鑰加密的主要缺點之一
对称加密的速度比公钥加密快很多,在很多场合都需要对称加密。
進階加密标准(Advanced Encryption Standard,AES),对称加密中最流行的算法之一。
非对称加密
公开密钥密码,公钥加密算法。
要两个密钥,一个是公开密钥,另一个是私有密钥;一个用作加密,另一个则用作解密。使用其中一个密钥拿明文加密后所得密文,只能用相对应个另一个密钥才能解密得到原本明文;甚至连最初用来加密个密钥也不能解。
RSA是最具影响力的非对称加密算法,三个字母是三位创始人的姓氏首字母。RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
阮一峰的文章
非对称加密另有一个用途是数字签名
Digital Signature
网站对敏感内容使用私钥生成摘要信息,该信息使用公钥解密后可以证实为由私钥所生成(?),且反映内容是否已被篡改,故可作为数字签名
为避免不怀好意的第三方冒充网站,提供公钥并发送密文给客户,应运而生”证书中心”(certificate authority,CA)。CA使用其私钥为官方公钥及其他信息加密,生成数字证书(Digital Certificate)。客户使用CA提供的公钥从数字证书中获取真实的网站公钥。
https协议
客户端向服务器发出加密请求。
服务器用自己的私钥加密网页以后,连同本身的数字证书,一起发送给客户端。
客户端(浏览器)的”证书管理器”,有”受信任的根证书颁发机构”列表。客户端会根据这张列表,查看解开数字证书的公钥是否在列表之内。
如果数字证书记载的网址,与你正在浏览的网址不一致,就说明这张证书可能被冒用,浏览器会发出警告”此网站的安全证书有问题 单击此处关闭该网页 继续浏览此网站(不推荐)”。
package.json
author
description
license
keywords
dependencies 和 devDependencies, peerDependencies, bundledDependencies, optionalDependencies
- npm install 命令 不加 —save 不会修改package.json
- npm install 命令 —save参数将package记入dependencies,—save-dev参数将package记入devdependencies
- 开发工具如glup,angular脚手架自动安装的jasmine、karma、tslint、chai等,以致于@angular/cli自身,@angular/compiler-cli等工具,以及用于编译器做类型识别的各种@type/XXX 应该放devdependencies
- 运行环境如Express,前端框架@angular/core以及可选包forms、animation等,弥补浏览器内核、版本等差异的腻子如core.js,应为dependencies 参考Angular Doc: npm packages
- 封装node.js api第三方工具如操作xml、mail、excel等,是业务不可或缺的,应属dependencies
- 重新编译electron的如node-ffi私以为其实并不会进入构建结果,应为dependencies
当有人准备在自己的程序中下载使用你的模块时,估计他们不想下载构建你使用的外部测试或者文档框架,为此宜将这些依赖项放在devDependencies里 npm doc
peerDependencies: peer意为同等地位的人,同龄人。peerDependencies将该模块的树形的依赖关系摊平到宿主的依赖环境中
bundledDependencies: 将依赖的包与当前模块绑定在一起, 如发布一模块做如下配置,npm pack该模块将获得包含”renderized”和”super-streams”的awesome-web-framework-1.0.0.tgz,package version另需在dependencies中指定1
2
3
4
5
6
7{
"name": "awesome-web-framework",
"version": "1.0.0",
"bundledDependencies": [
"renderized", "super-streams"
]
}
optionalDependencies 可选的依赖,有的依赖模块依赖于特定的运行环境,因此optionalDependencies的依赖项在安装失败的情况下不会影响整个安装结果
语义版本控制(Semantic Versioning)
MAJOR version when you make incompatible API changes,
MINOR version when you add functionality in a backwards-compatible manner, and
PATCH version when you make backwards-compatible bug fixes.
Use the tilde-character (~) to prefix the version of moment in your dependencies and allow npm to update it to any new PATCH release(补丁).
Use the caret-character (^) to prefix the version of moment in your dependencies and allow npm to update it to any new MINOR release(小版本).
本地依赖
1 | "qqsmodule": "file:../CustomModules/qqsmodule" |
package-lock
- 记录整个依赖树的具体版本, 即包括了依赖的依赖,
- 须提交package-lock 在npm install时安装指定的版本
- 每次npm update时依据package.json中的升级版本设置修改package-lock.json
version lens
VS Code extension 鼠标悬停在dependency的项上,可查看最新版本和依赖项目链接
关于版本号和构建编号
The standard build numbering convention makes use of a fourth numerical indicator which is appended
to the release number, where the fourth indicator is the build number.
- For verification builds, the build number starts with a “1”, and increments with each successive
build. For each successive release, the build indicator starts again with zero’s. - For development builds, the build number starts with “20001” and increments with each
successive build. For each successive release, the build indicator starts again with zero’s.
scripts
TypeScript
QQs:TS相比ES————静态类型,代码的可读性和可维护性
TS相比ES不只是静态类型,还有Class Interface Generics(泛型) Enum等
辩证地看,也有它地缺点如学习成本,搭框架地额外成本,与js库的兼容性,额外的编译过程等
官方Doc
在线编译器
调试
方法一
npm install typescript
add tsconfig.json1
2
3
4
5
6
7
8
9
10
11
12{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": true,
"outDir": "./dist",
"sourceMap": true
},
"include": [
"src/**/*"
]
}
add .vscode/tasks.json1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"type": "typescript",
"tsconfig": "tsconfig.json",
"problemMatcher": [
"$tsc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
Terminal—Run Task—Choose tsconfig.json
add .vscode/launch.json1
2
3
4
5
6
7
8
9
10
11
12
13
14{
"version": "0.2.0",
"configurations": [
{
"name": "launch",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/dist/main.js",
"args": [],
"cwd": "${workspaceRoot}",
"protocol": "inspector"
}
]
}
Run Debugging(Choose ‘launch’, the name definited in the launch.json)
方法二
npm i typescript node-ts
add tsconfig.js1
2
3
4
5
6
7
8
9
10
11
12{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": true,
"outDir": "./dist",
"sourceMap": true
},
"include": [
"src/**/*"
]
}
add .vscode/launch.json1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16{
"version": "0.2.0",
"configurations": [
{
"name": "Current TS File",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/node_modules/ts-node/dist/_bin.js",
"args": [
"${relativeFile}"
],
"cwd": "${workspaceRoot}",
"protocol": "inspector"
}
]
}
基本类型
- number
- boolean
- string
- []
- enum
- any
- void
- null 和 undefined
- never
关于枚举
定义一组常量1
2
3
4
5
6enum Direction {
Up = "↑",
Down = "↓",
Left = "←",
Right = "→",
}
类似map的用法1
2
3
4
5
6switch(key){
case Direaction.Up:
console.log('direction is up');
break;
...
}
类似interface的用法, 如 function Foo(direct: Direaction)
“类型谓词”1
2
3function isFish(pet: Fish | Bird): pet is Fish {
return (<Fish>pet).swim !== undefined;
}
定义类型保护函数isFish用以区分一个联合类型(Fish | Bird)的变量,依据是Fish类型存在swim属性
其意义无非就是把下列代码1
2
3
4
5
6if ((<Fish>pet).swim) {
(<Fish>pet).swim();
}
else {
(<Bird>pet).fly();
}
改为1
2
3
4
5
6if (isFish(pet)) {
pet.swim();
}
else {
pet.fly();
}
多数情况下还是用 typeof 和 instanceof
let 和 const 同es6
let const 声明的变量只在当前代码块中有效
1 | for (var i = 0; i < 10; i++) {} |
1 | for(let j = 0; j < 10; j++) {} |
以前需要立即执行表达式(IIFE)解决的问题
1
2
3
4
5
6
7 for (var k = 0; k < 5; k++) {
(function (k) {
setTimeout(function () {
console.log(k); //输出0,1,2,3,4
},0);
})(k);
}
1
2
3
4
5 for (let j = 0; j < 5; j++) {
setTimeout(function () {
console.log(j); //输出0,1,2,3,4
},0);
}
不存在变量提升
1
2
3
4
5 console.log(foo); // 输出undefined
console.log(bar); // 报错ReferenceError
var foo = 2;
let bar = 2;
不允许重复声明暂时性死区
即不允许在声明位置之前调用该变量
const 声明引用值不允许修改,然而const的对象内部状态是可以修改的。区分声明只读类型关键字readonly
1 readonly GIPX = 0x1a;
解构
1 |
接口
鸭子类型
1
2
3
4
5
6
7
8
9
10 interface LabelledValue
{
label: string;
}
function printLabel(labelledObj:LabelledValue)
{
console.log(labelledObj.label);
}
let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);
可见,参数对象并非实现接口,只需对外表现接口的特性
另外,接口里的属性可以定义为非必须的1
2
3
4interface SquareConfig {
color?: string;
width?: number;
}
定义可索引的类型
1
2
3
4
5
6 interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
如上,是一个接口的定义,符合该接口的属性可以number类型为索引。
另,索引亦可为string类型。注意当同时使用两种类型的索引,数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用 number 来索引时,JavaScript会将它转换成 string 然后再去索引对象。 就是说用 100 (一个 number )去索引等同于使用 “100” (一个 string )去 索引,因此两者需要保持一致。
interface 和 type:
如上所述,interface是接口,是一种规范,简单的对功能的抽象。接口可以用extends扩展(栗子略了)
type是类型, 多次声明的接口定义是扩展叠加的关系1
2
3
4
5
6
7
8
9
10interface WidgetProps{
click:any
}
interface WidgetProps{
drag:any
}
CanWidgetProperty : WidgetProps = {
click: handleClick;
drag: handleDrag;
}
type顾名思义是类型,可以是基础类型(或其组合,如用逻辑|的组合)的别名。与interface相比似乎更加固定、安全(不似interface灵活)
实现多个接口:1
let person: Person & AdditionalProperties
类
实现接口..
es6是没有constructor的,可以再琢磨下js原型篇。
ts中,类是具有两个类型:静态部分的类型和实例的类型。静态部分是类定义本身,实例部分就是生成的类的对象
constructor 存在于类的静态部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
tick();
}
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("tick tock");
}
}
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
这个是官方示例代码。为了实现定义一个符合ClockInterface接口规范的createClock方法。
而且应将符合ClockConstructor接口规范的类型作为返回值得类型
泛型
1 | function identity<T>(arg: T): T |
在es中class本质是函数,故class也可将泛型作为构造方法参数,并加以类型约束1
infer
1 | type ParamType<T> = T extends (param: infer P) => any ? P : T; |
infer表示P是待推断的参数类型,如T
never
不会返回结果的类型,一直是while(true)的函数,或者一定会抛出异常的函数
模块
export 和 import
namespace(存目)
从js迁移
参考TS Doc
元组
与数组的唯一区别是依次逐项指定了类型
适用于特定的数据元结构,比较现实的场景如csv文件的row
1 const newRow:[number,string,boolean] = [1,'老王',true]装饰器 Decorator
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上。 装饰器使用 @expression这种形式,expression求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息作为参数传入。
1 | import "reflect-metadata"; |
这里用到了反射1
2
3
4
5
6
7
8
9
10
11
12class Greeter {
@format("Hello, %s")
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
let formatString = getFormat(this, "greeting");
return formatString.replace("%s", this.greeting);
}
}
运行时变量属性未在类型声明中
使typeScript 识别未声明的属性 除了parameter:any 有以下几种方法更好的做法
- 重新声明中变量
1
2
3
4
5
6
7
8
9// types.d.ts
import 'some-library';
declare module 'some-library' {
export interface Person {
[key: string]: any; // 添加索引签名
email?: string; // 添加可选属性
}
} - 类型断言
1
2
3
4
5let personWithTypeAssertion: Person = {
name: "John Doe",
age: 30,
additionalProperty: "Some value" // TypeScript 不会报错
} as Person & { additionalProperty: string };typescript-eslint
见Typescript-ESLint
面试必备
typescript的特点
- 提供面向对面编程(OOP)的特性 如 类,接口,模块
- 静态类型检查
- ES6特性 箭头函数 变量声明等
- 可选参数
- 内置类型
优点和技巧
- 静态类型
- 扩展名为.d.ts的Definition文件提供对现有JavaScript库(如Jquery,D3.js等)的支持。
troubleshooting
fork-ts-checker-webpack-plugin error in undefined(undefined,undefined)
该插件与typescript类型检查有关 该报错原因难以定位 修改typescript到旧版本解决
场景:1
2
3
4"@craco/craco": "^6.0.0",
"@types/node": "^14.14.16",
"react": "^17.0.1",
"typescript": "4.1.3",
Interview Questions
该职位期望招聘高级软件开发人员 以完成基础软件开发 具备独立搭建框架能力和较丰富的前后端开发经验
1介绍一下原型链
2变量提升
- js中变量和函数的声明都会被提升到函数最顶部
- 这使得变量和函数在coding时可以先调用在声明
2属性绑定实现视图更新的原理
Angular的双向绑定原理:
React的虚拟dom和diff算法
虚拟dom是轻量化的js对象 用于描述真实的dom 当状态改变时 react通过比较虚拟dom的差异 最小化改动真实dom 从而提升性能
3编写单元测试用例
4只执行一次的生命周期钩子 constructor init之间进行了什么
| 钩子 | 目的 |
|---|---|
ngAfterContentInit | 在Angular将外部内容放到视图内之后。
ngAfterContentChecked | 在Angular检测放到视图内的外部内容的绑定后。
ngAfterViewInit | 在Angular创建了组件视图之后。
ngAfterViewChecked | 在Angular检测了组件视图的绑定之后。
constructor 依赖注入
5依赖注入 反射
6面向对象的核心——抽象
封装 继承 多态是面向对象的三个核心特征 对应的目的性是是代码具备可重用性、可扩展性,即可减少重复代码,进而使程序增加可维护性
面向对象未必是先进的,编程模式要根据需求而定,避免脱裤子放屁,近年流行的函数式编程就是与面向对象相斥的,在函数式编程中减少使用保存状态的‘对象’
7docker
8持续集成
前端表格1000w行数据流畅渲染
deepseek —— 前端
一、技术深度扩展能力
核心原理掌握
深入解释DOM树渲染机制(参考论文提及的节点树形结构抽象能力)
阐述AJAX异步通信的底层实现(如XHR对象与Fetch API差异)
展示CSS渲染层合成原理(如重排/重绘优化策略)
性能优化体系
优化维度 具体措施 考核要点
网络层面 HTTP/2协议应用、CDN加速策略 减少RTT时间
资源加载 按需加载、Tree Shaking 首屏加载时间优化
代码执行 Web Workers多线程优化 主线程阻塞规避
二、工程化实践能力
架构设计思维
展现B/S架构系统设计经验(参考论文的三层架构设计)
演示模块化开发能力(如Web Components应用)
数据库优化方案(MySQL索引策略、NoSQL选型)
质量保障体系
单元测试覆盖率(Jest/Mocha)
E2E测试实施(Cypress/Puppeteer)
持续集成部署(Jenkins/Travis CI)
三、软性能力表现
沟通演示技巧
使用语音模拟系统进行技术方案阐述(参考论文的语音面试模块)
白板编码时标注关键路径时间复杂度
职业形象管理
VR试衣系统准备的职业着装认知(参考论文的虚拟试衣功能)
简历制作突出开源项目贡献(GitHub Star/Fork数据)
四、前沿技术敏感度
新兴技术栈
WebAssembly在性能敏感场景的应用
Serverless架构的BFF层实践
WebGL/WebXR三维交互开发经验
标准演进跟踪
CSS Houdini底层API实践
ECMAScript提案阶段特性预研
W3C新规范解读(如WebGPU)
建议候选人准备3-5个典型优化案例,量化展示性能提升指标(如首屏加载从2.1s优化至780ms),并携带移动端适配、跨平台框架(Electron/Flutter)等扩展能力的实证材料。
自我介绍
面试自我介绍五句话公式:
我是谁+从哪里来+我做过什么+有什么成绩+为什么能胜任
Hexo TroubleShooting
Nginx
配置依赖库。
gcc(GNU Compiler Collection)
pcre依赖库
zlib依赖库
SSL依赖库
1 | yum install gcc pcre-devel zlib zlib-devel openssl openssl-devel |
安装NGINX
官网下载地址: http://nginx.org/en/download.html
—> 解压1
tar -zxvf nginx-1.14.2.tar.gz
z(gz格式)j(bz2格式)x(解压)v(显示所有过程)f(使用档案名称命名)
—> configure
进入解压目录下1
./configure
—>编译1
2make
make install
启动和停止
1 | /nginx/sbin/nginx |
—>查看进程1
ps -ef | grep nginx
访问index.html页面,404
—>检查端口1
telnet 127.0.0.1 8080
显示Connection closed by foreign host
—>查看和关闭防火墙1
2firewall-cmd --state
systemctl stop firewalld.service
—>服务开机启动1
2systemctl disable firewalld.service
systemctl enable nginx.service
手动下载源码,并编译安装的是没有nginx.service的,手动创建1
vi /lib/systemd/system/nginx.service
编辑内容如下1
2
3
4
5
6
7
8
9
10
11
12
13[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target
web服务及反向代理
/usr/local/nginx/nginx.conf1
2
3
4
5
6
7
8
9
10 server {
listen 8080; #nginx服务器的代理端口
server_name _;
location / {
proxy_pass http://172.18.78.14:6080; #需要反向代理的IP地址+端口
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
负载均衡
代理服务
Linux网卡重命名
查看RedHat版本1
cat /etc/redhat-release
1
yum install nginx
error:cannot find a valid baseurl
ping
connect:network is unreachable
ls /etc/sysconfig/network-scripts/
ifcfg-enp0s3 ifcfg-lo ….
其中ifcfg-lo是localhost配置
将第一个配置文件重命名1
mv ifcfg-enp0s3 ifcfg-eth0
查看网卡1
ip add
显示了lo和enp0s3
修改默认网卡设置
编辑/etc/default/grub文件,在GRUB_CMD_LINE_LINUX=””项中,插入”net.ifnames=0 biosdevname=0”
修改ip配置
注意1
DEVICE=eth0
1
ONBOOT=no //设置开机启动网卡,将值修改为“yes”
1
BOOTPROTO=static //默认为no,修改为static
重启
service network restart
reboot
video和视频流
直播原理
协议
H5 video标签
直播流的制作
Nginx+ffmpeg
安装
下载RTMP模块并重编译nginx
官方源代码https://github.com/arut/nginx-rtmp-module.git
配置
1 | ./configure --prefix=/usr/local/nginx --add-module=~/nginx-rtmp-module --with-http_ssl_module |
编译并安装
1 | make && make install |
nginx reload后报“open() “/usr/local/nginx/logs/nginx.pid” failed”,执行下面的命令,指定nginx的configure路径
1 | ./nginx -c /usr/local/nginx/conf/nginx.conf |
编译通过nginx可访问,还没完,配置nginx.conf,在末尾添加rtmp模块配置:
1 | rtmp{ |
hls_path是分割文件存储路径
在http模块中添加服务路径1
2
3
4
5
6
7
8
9
10
11
12http {
server {
location /hls{
types{
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /usr/local/userdata/live;
add_header Cache-Control no-cache
}
}
}
安装流媒体文件转换工具ffmpeg
官方release:http://www.ffmpeg.org/download.html#releases
解压1
tar jxvf ffmpeg-4.1.3.tar.bz2
执行configure报“yasm/nasm not found or too old. Use —disable-x86asm for a crippled build”,ffmpeg默认的编译器未安装,需使用—disable-x86asm
将本地视频文件通过nginx推流
本地视频文件kon.mp4
推送RTMP流
1 | ffmpeg -re -i test.mp4 -vcodec libx264 -acodec acc -f flv rtmp://127.0.0.1:1935/rtmplive/rtmp |
推送HLS流
1 | ffmpeg -re -i test.mp4 -vcodec libx264 -acodec acc -f flv rtmp://127.0.0.1:1935/hls/stream |
这里有一个关于编码器的坑
vcodec acodec 分别指明了视频、音频的编码器,其实这里可以用copy也就是不需要转码,从官方GitHub下载安装的ffmpeg是没有libx264的编码器的,故而在执行上述推流命令时报unkown encoder libx264
而通用的h.264视频编码器是叫x264:https://www.videolan.org/developers/x264.html
安装x264需要将类库提供给外部应用程序(如ffmpeg)1
2
3./configure –enable-shared
make && make install
配置编译的时候最好有—prefix指明安装路径,否则一般默认到/usr/local/lib路径下
需要将/usr/local/lib路径加入共享库配置文件/etc/ld.so.conf中1
2
3echo "/usr/local/lib" >> /etc/ld.so.conf
ldconfig
编译安装含外部解码器的FFmpeg1
2
3./configure --enable-static --enable-gpl --enable-libx264 --extra-cflags=-I/usr/local/include --extra-ldflags=-L/usr/local/lib
make && make install