(一)计算机的 24种设计模式
计算机科学中的设计原则可以是多种多样的,以下是一些常见的设计原则:
- 单一职责原则 (Single Responsibility Principle, SRP) :一个类应该只有一个引起变化的原因。
- 开闭原则 (Open/Closed Principle, OCP) :软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
- 里氏替换原则 (Liskov Substitution Principle, LSP) :子类必须能够替换掉它们的父类而不影响程序的正确性。
- 依赖倒置原则 (Dependency Inversion Principle, DIP) :高层模块不应该依赖于低层模块,二者都应该依赖于抽象。
- 接口隔离原则 (Interface Segregation Principle, ISP) :不应该强迫客户端依赖于它们不使用的接口。
- 合成/聚合复用原则 (Composite/Aggregate Reuse Principle, CARP) :优先使用合成/聚合,而不是继承。
- 最少知识原则 (Principle of Least Knowledge, Law of Demeter) :一个软件实体应当尽可能少地与其他实体发生相互作用。
- 分离关注点 (Separation of Concerns, SoC) :将一个程序分解为不同的部分,每个部分关注一个单独的关注点。
- 迪米特法则 (Law of Demeter, LoD) :一个对象应该对其他对象有尽可能少的了解,只与其直接朋友通信。
- DRY原则 (Don't Repeat Yourself, DRY) :不要重复编写重复的代码,而应该将重复的逻辑封装成可复用的模块。
- KISS原则 (Keep It Simple, Stupid, KISS) :保持系统设计简单,避免过度复杂化。
- YAGNI原则 (You Aren't Gonna Need It, YAGNI) :不要为未来的需求做过度设计,只实现当前所需的功能。
- GRASP原则 (General Responsibility Assignment Software Patterns) :将责任分配给各个类、模块或对象时的一些指导原则。
- ACID原则 (Atomicity, Consistency, Isolation, Durability) :事务处理的四个基本特性。
- CAP原则 (Consistency, Availability, Partition tolerance) :分布式系统中的三个基本属性,不可能同时满足。
- CQRS原则 (Command Query Responsibility Segregation) :将命令(修改状态)与查询(返回状态)分离。
- 面向对象设计原则 (Object-Oriented Design Principles) :封装、继承、多态。
- 面向切面编程 (Aspect-Oriented Programming, AOP) :将横切关注点与核心业务逻辑分离,提高模块化和可维护性。
- 领域驱动设计 (Domain-Driven Design, DDD) :将软件系统的设计与特定业务领域的概念相对应。
- 事件驱动架构 (Event-Driven Architecture, EDA) :基于事件的异步架构,用于处理不同组件之间的通信。
- 微服务架构 (Microservices Architecture) :将单个应用程序拆分为一组小型、独立的服务,每个服务都围绕业务功能构建。
- 服务导向架构 (Service-Oriented Architecture, SOA) :将应用程序设计为一组相互连接的服务,每个服务都能够独立地执行特定的功能。
- 演化式架构 (Evolutionary Architecture) :支持系统随着时间和需求的变化而演变的架构。
- 敏捷原则 (Agile Principles) :一组价值观和原则,用于指导敏捷软件开发方法的实践。
这些原则并不是固定不变的,而是随着技术和行业的发展而不断演变和改进的。
注:大公司、自研公司爱问设计模式和算法。在基础知识十分扎实的情况下可以再去准备,逐渐深入了解。
(二)同步和并行
同步(Synchronization)和并行(Parallelism)是计算机科学中常见的两个概念,它们在多线程编程、分布式系统以及计算机体系结构等领域都有重要作用。
-
同步:
- 同步是指控制多个线程或进程之间的执行顺序,以确保它们在必要时能够正确地协调工作。
- 同步通常涉及使用锁、信号量、条件变量等机制来保证对共享资源的安全访问,避免数据竞争和不一致性问题。
- 同步机制可以保证程序的正确性,但可能会引入性能开销和死锁等问题。
-
并行:
- 并行是指多个任务在同一时刻同时执行,利用多个处理单元(如多核处理器)来加速程序的执行速度。
- 并行通常涉及将任务分解成更小的子任务,并在不同的处理单元上同时执行这些子任务。
- 并行可以显著提高程序的性能和吞吐量,但也可能引入竞争条件和数据一致性的问题。
在实际应用中,同步和并行经常同时存在,并且需要综合考虑它们之间的相互影响。例如,在多线程编程中,需要通过合适的同步机制来保护共享资源的一致性,同时利用并行执行来提高程序的性能;在分布式系统中,需要通过消息传递和分布式算法来实现节点之间的同步和协作,以实现分布式并行计算。
总的来说,同步和并行是两个相互关联但又有区别的概念,它们在计算机系统中共同发挥着重要的作用,对于实现高性能、高可靠性的应用程序至关重要。
关于同步、异步、多线程
同步:上往下,前面不执行完毕,不会执行后面的(有耗时操作,会让用户感觉卡顿)
异步:
a. Promise管理异步,
b. then,catch链式编程
b.async和await代码就是类似同步的执行方式
c.Promise的静态方法管理多个异步,Promise.all
d.* Promise本质还是单线程的,核心是利用了 任务队列+事件循环
(三)资讯类的应用,触底加载,或者是长列表的你是怎么优化的?
1.最开始用的是ForEach,初期数据量不大的情况下,不卡
-
测试的时候发现,数据越来越多之后就出现了卡顿
a.【数据多-渲染的组件多-耗费手机的性能-卡顿】
b.只需要保证渲染的组件不是那么多即可
c.发现了有一个叫做【lazyForEach】的东西
3.当时我还在做其他的模块,这个就交给【小伙伴】去研究了
4.整合进来之后确实不卡了,虽然不是我做的,但是原理我了解过
a.只渲染用户看到的组件,【超出了屏幕之后,组件会被销毁】
b.不耗费性能了
(四)普通函数和箭头函数
箭头函数和普通函数的区别主要体现在以下几个方面:
1、语法简洁性
箭头函数使用箭头(=>)来定义,语法更加简洁,可以省略function关键字和圆括号(当只有一个参数时),甚至省略大括号(当函数体只有一条语句时)。而普通函数需要使用function关键字进行定义,且参数需放在圆括号内,函数体放在大括号内。
2、this指向
在普通函数中,this的值是在函数被调用时确定的,它指向调用该函数的对象。如果没有明确的调用者,或者是在全局作用域中调用,this会指向全局对象(在浏览器中通常是window)。而在箭头函数中,this的值是在函数定义时就已经确定的,它指向定义箭头函数的上下文环境中的this。箭头函数没有自己的this,它会捕获其所在上下文的this值,作为自己的this值,且这个this值在函数执行过程中是不可改变的。因此,箭头函数更适合在需要保留上下文环境中的this值时使用。
3、arguments对象
普通函数会创建自己的arguments对象,该对象包含了函数调用时传入的所有参数。而箭头函数没有自己的arguments对象,它会继承外层作用域的arguments对象。如果箭头函数需要访问函数的参数列表,可以使用rest参数(...args)来代替。
4、构造函数
普通函数可以被用作构造函数来创建对象实例,使用new关键字进行实例化。而箭头函数不能用作构造函数,不能使用new关键字进行实例化,否则会抛出错误。这是因为箭头函数在创建时不会为其分配[[Construct]]方法,即没有构造能力。
5、其他特性
箭头函数还具有一些其他特性,如不能通过call()、apply()或bind()方法来改变this的指向,不能使用yield关键字,因此不能用作Generator函数,以及没有原型属性(prototype)等。35 总的来说,箭头函数和普通函数在语法、this指向、arguments对象、构造函数以及其他特性方面都存在明显的区别。在选择使用哪种函数时,需要根据具体的使用场景和需求来决定。
- 普通函数会出现this指向错误的问题
- 箭头函数可以绑定this指向
- 前端面试问得多
(五)【隐私相册】的业务流程
典型问题的典型对答
你做过最有成就感的功能是什么?
a. 之前做的大部分模块的功能,和之前做过的不太一样,我申请我来做,搞定了,所以记忆尤新。
——之后打住话题,面试官大概率会跟着这个话题追问下去,之后就切到自己擅长的问题。