flex
# 父属性
flex-direction:设置主轴的方向
justify-content:设置主轴土的子元素排列方式
flex-wrap:设置子元素是否换行
align-content:设置侧轴上的子元素的排列方式(多行)
align-items:设置侧轴上的子元素排列方式(单行)
flex-flow:复合属性,相当于同时设置了flex-direction和flex-wrap
flex-basis:宽/高
# 子属性,固定div,flex:1表示自适应占比1份
# 等同于 flex: 1 1 auto;
# flex-grow: 1;元素占比多少份 flex-shrink: 1;收缩flex-basis: auto;剩余空间大小
flex:1
- flex-basis
效果等同于:width;不同点在:flex-direction为row控制的是width;flex-direction为column 控制的是height;
- 设置了flex-basis的值,这时候width会忽略,元素的宽度用flex-basis的值表示
#互斥锁/共享锁
互斥锁:访问共享资源进行加锁,访问完后解锁。 加锁后,其他试图再次加锁的线程会被阻塞,直到当前进程解锁。
共享锁:共享锁从字面来看也即是允许多个线程共同访问资源,但其他线程不能写。
#Vue相对jQuery的优势
- 减少DOM操作
- 双向数据绑定、数据响应式、组件化
#栈空间和堆空间
- 栈空间:几M空间,生长方式是向下的,也就是向着内存地址减小的方向消耗空间。编译器自动分配释放 ,存放函数的参数值,局部变量的值等
- 堆空间:几G空间,生长方式是向上的,也就是向着内存地址增大的方向消耗空间。程序员分配释放,若程序员不释放,程序结束时可能由OS回收
#拓扑排序
- 针对:有向无环图,对入度为0的入队,结果不唯一
- 算法:广度优先遍历、深度优先遍历
#setTimeout/setInterval/requestAnimationFrame
概念:Settimeout 指定时间执行一次;setInterval:指定时间循环执行
setTimeout误差问题:
-
问题原因:setInterval、setTimeout都属于宏任务,都会出现误差,这源于js的单线程。
-
解决办法:1.获取误差并修正回调执行的时间;2.动态修正时间参数
clearTimeout / clearInterval能否相互清除对方定时器:
- 能;不建议这么干
setTimeout延迟写0与不写区别:
# 不写,默认是4ms,写0会更快些,写0也不会立即执行;
setTimeout/requestAnimationFrame区别:
- setTimeout:
# 无法保证时间上精确(无法跟浏览器重绘时间重合,会出现抖动或跳跃情况,效果不好)
- requestAnimationFrame:
# 浏览器专门为动画提供的 API:请求动画帧
# 不会进行重绘或回流;
#GPU/GPU
# CPU 是大脑----(全能),处理电脑所有操作,也可渲染动画,效果没GPU好
# GPU 是显卡----(专一渲染动画/计算),渲染动画/图像/计算等
#echart
EChart.resize()自适应div
#动态规划/分治法异同
共同点:将大问题转换成多个最优子问题;
# 动态规划:先计算最小的子问题的最优解,再一层层组合成大问题的最优解(每次会保留上一次的结果)
# 分治法:分治采用的递归写法
# 场景:针对有重复子问题时用“动态规划”;没有就可以用分治法-递归
#暂时性死区
# 场景:(补充:const声明不赋值是直接报错的)
# 描述:let只声明没有赋值
let a;
console.log(a)# 这里就是暂时性死区
a = 2
#Object.defineProperty属性
get#查看
set#修改
value# 当前值
writable# 是否可重写
enumerable# 是否可枚举(用来遍历的)
configurable# 是否可再次修改配置项
#纯函数/高阶函数/组合函数/函数柯里化
- 纯函数
# 概念:相同的输入永远会得到相同的输出;如:slice 不会改变原数组;splice 会改变原数组
- 高阶函数
# 概念:一个函数可以接收另外一个函数作为参数;如filter、map、reduce
- 组合函数
# 函数里面调函数,建议尾部调用
- 函数柯里化
# 函数都不会立即执行,而是等待调用;fn()()()
有的时候同一种规则可能会反复使用(比如校验手机的参数);返回的函数都不会立即执行,而是等待调用
//普通函数
const sum1 = (x, y, z) => {
return x + y + z
}
//函数柯里化
const sum2 = x => {
return function (y) {
return function (z) {
return x + y + z
}
}
}
// 普通函数调用
sum1(1, 2, 3)
// 函数柯里化调用
sum2(1)(2)(3)
#函数式编程
概念:纯函数、函数柯里化、组合函数、with、eval、严格模式都是函数式编程中的概念
# with:是一个函数,将代码的作用域设置到一个特定的对象中;with(document){var Div = getElementById("Div");}
# eval:字符串变成代码执行,存在安全隐患
# 严格模式:use strict 来开启严格模式,是一种规范:无法意外的创建全局变量以及变量定义了要使用
#script标签属性
# src、type、charset、language、defer、async
#Cesium地球三维映射到二维
Cesium 核心:相机(flyTo切换视角带动画/lookAt视觉锁定/setView视角切换)、坐标系(Cartographic-wGS84经纬度坐标系/Cartesian3笛卡尔空间直角坐标系)、地形图层、3DTiles、时间系统、粒子系统
- 三维坐标:通过经度、纬度、高度、来确定地球上的每个点
- 三维映射:通过 Web Mercator |WebGL,三维几何数据映射到二维平面上
- 地图加载:采用3D Tiles瓦片数据加载地球模型 ,3D Tiles是三维地理数据的规范。其中包含了三维几何信息、纹理贴图、属性等等
3DTiles数据格式:
- 头文件:版本、坐标系、地理范围
- 瓦片集:数据瓦片的容器,如根瓦片的位置、边界框
- 数据瓦片:瓦片集中的最小数据单元,包含了特定区域的三维几何信息、纹理贴图、属性和其他相关数据。
- 扩展:扩展表示特定的地理数据类型、添加自定义样式/属性
#二叉树的遍历
前/中/后/层序遍历;深度优先/广度优先遍历;
深度优先:就是前序遍历,先找到没有后代节点的节点;
广度优先:就是层序遍历,一层一层找;
#three.js立体展示模型
# 1 创建场景和渲染器
# 2 创建相机
# 3 创建模型var loader = new THREE.OBJLoader()引入.obj模型;loader.load(加载模型)
# 4 设置材质和纹理(可选)
# 5 创建轨道控制器--3d展示
# 6 开始渲染场景--render方法
- 3d是如何在2d上渲染
使用 WebGL 技术将 3D 场景渲染到 2D 页面上;将 3D 场景渲染到画布canvas上
#npm包发布/pnpm
- npm包的发布流程
核心:是配置package.json:
{
"name": "my_first_npm",
"version": "1.0.0", //标明发布时的版本
"description": "my first npm package",
"main": "index.js", //写清楚入口文件
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [ //标明关键字,方便其他人检索我们所创建的包
"npm",
"packge"
],
"author": "wlaozhichi",
"license": "ISC" //使用ISC作为许可证
}
然后:index.js是包的内容(比如一个时间格式转换包)
最后:发布包
# 安装nrm --npm i -g nrm
# 镜像切换为npm --nrm use npm
# 登录npm账号 --npm login
# 发布包 --npm publish;发布包的时候要慎重,尽量不要往npm上发布没有意义的包!
补充:nrm命令
nrm -h # 显示所有命令
nrm current # 显示当前镜像名称
nrm use <name> # 切换镜像
nrm add <name> <url> # 新增镜像
nrm del <name> # 删除镜像
nrm ls # 查看镜像列表
nrm test <name> # 测试镜像
- pnpm概念:pnpm由npm/yarn衍生而来,解决了npm/yarn内部潜在的bug,优化了性能;
#es5实现const
用defineProperty的writable为false属性来实现
var __const = function __const (data, value) {
window.data = value // 把要定义的data挂载到window下,并赋值value
Object.defineProperty(window, data, { // 利用Object.defineProperty的能力劫持当前对象,并修改其属性描述符
enumerable: false,
configurable: false,
get: function () {
return value
},
set: function (data) {
if (data !== value) { // 当要对当前属性进行赋值时,则抛出错误!
throw new TypeError('Assignment to constant variable.')
} else {
return value
}
}
})
}
__const('a', 10)
console.log(a)
delete a
console.log(a)
for (let item in window) { // 因为const定义的属性在global下也是不存在的,所以用到了enumerable: false来模拟这一功能
if (item === 'a') { // 因为不可枚举,所以不执行
console.log(window[item])
}
}
a = 20 // 报错
#父组件修改子组件样式
- Props 传递样式,修改class
- 作用域插槽
- eventbus全局事件总线、状态管理器vuex
#父子组件获取ref
- 父组件直接获取子组件的ref
<ChildComponent ref="myChildRef"></ChildComponent>
const myChildRef = ref(null)
- 子组件获取父组件ref---1、provide/inject、2、组件传参
<template>
<div ref="parentRef">
<ChildComponent></ChildComponent>
</div>
</template>
const parentRef = ref(null);
provide('parentRef', parentRef);
// 子组件获取父组件ref:inject['parentRef']
#为什么promise能一直.then下去
.then()
方法返回的是一个新的Promise对象,因此可以链式调用
// 创建一个Promise对象
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('First');
}, 1000);
});
// 连续调用.then()方法
promise
.then(result => {
console.log(result); // 输出:First
return 'Second';
})
.then(result => {
console.log(result); // 输出:Second
return 'Third';
})
.then(result => {
console.log(result); // 输出:Third
});
#defineExpose
defineExpose概念:向父组件暴露一些属性或方法,以便父组件可以访问它们
- 子组件暴露-方法/变量
<button @click="increment">增加计数</button>
....
import { defineExpose, ref } from 'vue';
...
defineExpose({
count,//变量
increment//方法
});
- 父组件接收---通过ref接收子组件暴露的方法/变量
<ChildComponent ref="childRef"></ChildComponent>
...
import { ref } from 'vue';
const childRef = ref(null);
...
childRef.value.count; // 子组件的 count 属性
childRef.value.increment(); // 调用子组件的 increment 方法
#koa洋葱模型
洋葱模型概念:
- 一种中间件处理的设计模式;核心思想:将中间件按照特定的顺序层层包裹,然后再逆序执行,形成类似洋葱结构。
为什么出现洋葱模型/目的:
- 洋葱模型的设计目的是为了实现更灵活扩展的中间件处理流程。它允许在请求的处理过程中,按照一定的顺序执行多个中间件;
# context:请求和响应相关信息的上下文对象
# next:是一个函数;调用 next 函数将控制权传递给下一个中间件
const Koa = require('koa');
const app = new Koa();
// 中间件1
app.use(async (context, next) => {
console.log('Middleware 1 - before');
await next(); // 调用下一个中间件
console.log('Middleware 1 - after');
});
// 中间件2
app.use(async (context, next) => {
console.log('Middleware 2 - before');
await next(); // 调用下一个中间件
console.log('Middleware 2 - after');
});
// 中间件3
app.use(async (context, next) => {
console.log('Middleware 3 - before');
await next(); // 调用下一个中间件
console.log('Middleware 3 - after');
});
// 处理请求
app.use(async (context) => {
console.log('Request handler');
context.body = 'Hello, Koa!';
});
app.listen(3000);
洋葱模型的执行流程如下:
- 当有请求到达 Koa 应用程序时,会从第一个中间件开始执行
- 当一个中间件被调用时,它可以执行一些操作,并通过调用 next 函数将控制权传递给下一个中间件
- 在传递控制权给下一个中间件之前,当前中间件会暂停执行,并等待下一个中间件执行完成后再继续执行
- 当下一个中间件执行完成后,执行权会返回给当前中间件的下一个代码行
- 当所有中间件都执行完成后,执行权会回到最初的中间件,然后逆序执行
#怎么开启GPU加速
- 使用特定的CSS属性,如
transform
等,触发GPU加速 - 使用WebGL进行高性能的3D图形渲染,利用GPU的计算能力
- 使用Canvas API绘制2D图形,浏览器通常会将绘图操作委托给GPU加速处理
- 在处理视频时,使用硬件加速的
<video>
元素来提高视频播放性能
#文件名hash化
常见的哈希算法(如MD5、SHA-1、SHA-256);
import md5 from 'md5';// 导入MD5算法的库
const fileName = 'example.txt';
const hashFileName = md5(fileName);
#base64/blob区别
- Base64:二进制数据转化为ASCII 字符串;通过编码/解码来传输数据
- Blob:是数据类型,用于存储二进制数据,可以表示任意类型的二进制数据(图像、音频、视频);场景:文件上传/下载