2024/03/1, 每日3题
问题1:实现JS算法题「旋转数组」?
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: [1, 2, 3, 4, 5, 6, 7] 和 k = 3 输出: [5, 6, 7, 1, 2, 3, 4] 解释: 向右旋转 1 步:
[7, 1, 2, 3, 4, 5, 6] 向右旋转 2 步: [6, 7, 1, 2, 3, 4, 5] 向右旋转 3 步: [5, 6, 7, 1, 2, 3, 4]
示例 2:
输入: [-1, -100, 3, 99] 和 k = 2 输出: [3, 99, -1, -100] 解释: 向右旋转 1 步: [99, -1, -100, 3] 向右旋转 2 步: [3, 99, -1, -100]
1 2 3 4 5 6 7 8 9 10 11 | const rotate = (nums: number[], k: number): number[] => { const copyArr = JSON.parse(JSON.stringify(nums)); copyArr.unshift(copyArr.pop()); const i = k - 1; if (i >= 0) { return rotate(copyArr, i); } else { return nums; } } rotate([1, 2, 3, 4, 5, 6, 7], 3); |
问题2:简述Javascript 抽象工厂模式 ?
抽象工厂模式是一种设计模式,它提供了一种方式来创建一系列相关或依赖对象的工厂,而无需指定具体的类。这种模式有助于封装一组具体工厂的创建逻辑,从而使得客户端代码可以与抽象工厂接口交互,而无需关心具体工厂的实现细节。
在 JavaScript 中,抽象工厂模式通常以对象字面量或者构造函数的形式实现。下面是一个简单的示例来说明抽象工厂模式的基本原理:
// 抽象工厂 function ShapeFactory() { this.createCircle = function() { // 创建圆形对象的具体逻辑 return new Circle(); }; this.createSquare = function() { // 创建正方形对象的具体逻辑 return new Square(); }; } // 具体工厂实现 function Circle() { this.draw = function() { console.log('画一个圆形'); }; } function Square() { this.draw = function() { console.log('画一个正方形'); }; } // 使用抽象工厂创建对象 const factory = new ShapeFactory(); const circle = factory.createCircle(); const square = factory.createSquare(); circle.draw(); // 输出: 画一个圆形 square.draw(); // 输出: 画一个正方形
-
在这个示例中,
ShapeFactory
充当了抽象工厂的角色,它包含了用于创建不同形状对象的方法。Circle
和Square
分别是具体工厂的实现,它们实现了相应的创建逻辑。使用抽象工厂模式的主要优点包括:
- 客户端代码与具体工厂的实现解耦,因此可以更容易地进行替换和扩展。
- 通过抽象工厂接口创建对象,可以隐藏具体工厂的实现细节。
然而,抽象工厂模式也有一些缺点,例如增加新的产品类可能需要修改抽象工厂接口,从而引起一系列相关的变更。
总的来说,抽象工厂模式在一些情况下可以提供一种灵活的解决方案,特别是当需要根据不同的条件创建一组相关的对象时。
问题3:简述ES6 的 class 和构造函数的区别 ?
-
语法:
- 在 ES6 中,
class
关键字提供了一种更加简洁、面向对象的类定义语法,使得创建和继承类更加直观和易于理解。 - 构造函数是在 ES6 之前就存在的方式,通过
function
关键字来定义。虽然构造函数也可以用于创建类似于类的结构,但语法和继承的实现相对更为繁琐。
- 在 ES6 中,
-
继承:
- 使用
class
关键字可以更容易地实现类之间的继承关系,通过extends
关键字和super
关键字来进行继承和调用父类的构造函数。 - 在构造函数中,继承是通过原型链和原型继承来实现的,需要手动设置子类的原型对象并且调用父类构造函数来确保正确的继承行为。
- 下面是一个使用
class
关键字和构造函数来定义和继承类的简单示例: -
使用
class
关键字: -
class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } class Dog extends Animal { speak() { console.log(this.name + ' barks.'); } } const dog = new Dog('Buddy'); dog.speak(); // 输出: Buddy barks.
- 使用构造函数和原型链继承:
function Animal(name) { this.name = name; } Animal.prototype.speak = function() { console.log(this.name + ' makes a noise.'); } function Dog(name) { Animal.call(this, name); } Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; Dog.prototype.speak = function() { console.log(this.name + ' barks.'); } const dog = new Dog('Buddy'); dog.speak(); // 输出: Buddy barks.
总的来说,class
关键字提供了更直观和简洁的方式来定义和继承类,而构造函数需要手动处理原型链和原型继承,更为繁琐和容易出错。因此,通常情况下建议使用 class
关键字来定义类和继承关系。
当然也有其他细微的差别如下图
坚持不懈,加油!!!坚信努力不一定能上岸,但不努力永远上不了岸。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理