题目来源: 牛客
企业级开发整体流程有哪些
- 项目启动
- 需求调研->需求文档
- 系统设计->设计文档
- 程序开发->开发文档
- BUG测试->测试文档
- 验收
- 维护
遇到技术难题怎么办
- 分析可能出现的原因
- 查找搜索引擎
- 寻问文心一言等对话模型
- 打断点,寻找问题复现
- 再一次归纳分析
- 询问师傅或更高级的工程师
常用的设计模式
- 工厂模式
- 简单工厂模式
- 抽象工厂模式
- 单例模式
- 懒汉单例
- 饿汉单例
- 装饰器模式
- 策略模式
- 代理模式
- 观察者模式
- 发布订阅模式
单例模式具体实现和原理
单例模式涉及单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建
ts
// 懒汉单例
class LazySingleInstance {
private constructor {}
private static instance: LazySingleInstance;
static getInstance() {
if (!LazySingleInstance.instance) {
return LazySingleInstance.instance;
}
LazySingleInstance.instance = new LazySingleInstance();
return LazySingleInstance.instance;
}
}
// 饿汉单例
class HungrySingleInstance {
private constructor {}
private static instance = new HungrySingleInstance();
static getInstance() {
return HungrySingleInstance.instance;
}
}
发布订阅模式如何实现
js
class Event {
constructor() { this.events = {} }
// 订阅
on(type, callback) {
if (this.events[type] === undefined) this.events[type] = [];
this.events[type].push({ listener: callback });
}
// 发布
emit(type. args) {
this.events[type].forEach(ele => {
ele.listener(args)
});
}
}
发布订阅模式存在的风险
最大的缺点是松耦合,需要中间的代理,增加了系统的复杂度
TS泛型
泛型的特点就是带有"类型参数"
ts
function getFirst<T>(arr: T[]): T {
return arr[0];
}
什么情况用枚举类型
用于组合一系列常量从而实现共享复用
interface递归结构如何处理
interface可以在结构定义中引用interface定义的接口
典型ES6新特性
- 展开运算符
- 剩余参数
- 字符串插值
- 属性简写
- 对象方法简写
- 解构赋值
- 数组新方法
- Promise
- 模块化
async await和promise什么情况下用哪种
async/await适用于异步请求相互独立的情况
Promise适用于同时进行多个异步请求的情况
promise.all其中一个接口挂了有什么后果
如果有一个接口挂了,那么会立刻将其reject掉,不再等待其他异步操作执行
async await接口挂了怎么处理
会直接抛出错误,可以用try/catch捕获
promise对象的本质
Promise是一个对象,代表了一个异步操作的最终完成或者失败,本质上Promise是一个函数返回的对象,可以在上面绑定回调函数,就不需要一开始把回调函数作为参数传入
promise对象里面做了什么事
promise封装AJAX怎么用
js
const ajax = (url) => {
return new Promise((resolve, reject) => {
const req = new XHLHttpRequest();
req.open("GET", url, true);
req.onload = () => req.status === 200 ? resolve(req.responseText) : reject(new Error(req.statusText));
request.onerror = () => reject(new Error(req.statusText));
request.send();
});
}
const url = "/ajax/get";
ajax(url).then(value => console.log(value)).catch(error => console.log(error));
构造函数、实例、原型三者关系
每一个构造函数有一个prototype指向其原型对象
每一个原型对象有一个constructor指向其构造函数
每一个实例对象有一个__proto__指向其原型对象
字符串的constructor是什么
字符串的构造函数是String。当String作为构造函数使用时,会创建一个String对象而非原始数据类型;而被作为函数调用时,会将参数强制转换成一个字符串原始类型
类的私有成员和共享成员
- public: 默认值,没有访问限制
- protected: 只允许在类的内部以及直接子类中访问
- private: 只允许在类的内部访问
- static: 静态变量,与实例无关
用面对对象思想抽象组件
bind、apply和call的区别
call和apply的区别在于apply的传参使用的是数组
call和bind的区别在于bind不会离开调用函数
数组操作方法里比较方便匹配是什么API
Array.find
遍历数组里面返回新的数据结构
- for
- while
- for-in
- for-of
- forEach
- map
什么情况下用不用=
绝大多数场合可以直接使用===,只有检测是否为null/undefined时可以使用==
数据类型判断
- 基本数据类型:typeof
- 通过对象类型判断: instance of
- 根据原型链判断: prototype
- 根据构造器判断: constructor
为什么Object.prototype.toString().call(obj)需要用call,apply可以么
set和map生成的数据怎么转数组
使用Array.from即可
webpack怎么处理各种loader和plugin以及webpack的生命周期
loader就是一个函数,接受原始资源作为参数,输出进行转换后的内容
plugin会在webpack生命周期中监听事件,并在合适的时机改变输出结果
- beforeRun: 读取配置之前
- run: 开始编译
- watchRun
- beforeCompile: 使用webpack-dev-server时会调用
- compile: 开始编译时
- thisCompilation: 创建新的Compilation对象时
- compilation: 生成新的Compilation对象时
- emit: 生成资源之前
- afterEmit: 生成资源之后
- done: 编译完成时
- assetEmitted: 所有资源打包完毕后
介绍广度优先遍历和深度优先遍历的特性和区别
广度优先遍历
特点是回放。
- 从图中某顶点v出发,在访问了v之后依次访问v的各个未访问的邻接点
- 然后分别从这些邻接点出发依次访问它们的邻接点,并使得先被访问的顶点的邻接点先于后被访问的顶点的邻接点,直到图中所有已被访问顶点的邻接点都被访问到
- 如果此时图中尚有顶点渭北访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直到图中所有顶点都被访问到为止
深度优先遍历
特点在于回溯
- 假设初始状态是图中所有顶点均未被访问
- 从某个顶点触发,然后一次从它的各个未被访问的临界点出发深度优先搜索遍历图,直至图中所有和初始点有路径相通的顶点都被访问到
3 若此时尚有未被访问到的顶点,那么则另选一个未被访问的初始点作为起点,重复上述过程
算法:深度优先遍历和广度优先遍历
企业的软件项目开发你一定要知道的那些流程!
程序员遇到技术问题该怎么解
如何理解这6种常见设计模式?
菜鸟教程
如何使用js来实现一个发布订阅模式
设计模式之发布订阅模式------ 一文搞懂发布订阅模式
阮一峰TypeScripe教程
TypeScript字符串枚举,以及何时和如何使用它们
9个常用ES6特性归纳(一般用这些就够了)
Promise和async/await的两种常用的实际应用场景
async,await做错误处理,每请求一个接口都要try,catch一下吗?
JavaScript------promise(一)基础篇
5分钟带你搞懂 构造函数、原型对象、实例对象、原型、原型链
MDN官方文档
ts class中的成员可见性(public,protected,private,static)
手写Webpack生命周期及其实现过程
彻底掌握 Webpack 中 Loader 和 Plugin 的机制
js判断数据类型常用的6种方法