掌握JavaScript面向对象编程核心密码:深入解析JavaScript面向对象机制对象基础、原型模式与继承策略全面指南,高效创建高质量、可维护代码

在这里插入图片描述

ECMAScript(简称ES,是JavaScript的标准规范)支持面向对象编程,通过构造函数模拟类,原型链实现继承,以及ES6引入的class语法糖简化面向对象开发。对象可通过构造函数创建,使用原型链共享方法和属性,实现继承、封装和多态等面向对象特性。

ECMAScript的面向对象技术极大提升了JavaScript的代码组织度和复用性,通过类和继承机制促进了模块化编程,增强了代码结构的清晰度与可维护性。封装、继承、多态等特性支持复杂应用开发,是构建可扩展、易管理的大型项目的基础,对提升开发效率和代码质量至关重要。

本文详细介绍了JavaScript 对象概念原型模式创建对象的过程(Object 创建对象、构造函数 创建对象、原型模式 创建对象)以及机制策略(__proto__和 prototype、constructor),继承机制(原型链继承、构造函数继承、组合继承、寄生式继承、寄生组合式继承、ES6 Class继承)等内容。

一、JavaScript 对象

ECMAScript(JavaScript)中的对象是一种数据结构,用于存储键值对(property-value pairs),其中键(property)通常是字符串类型,值(value)可以是任意数据类型,包括其他对象。对象是JavaScript中最基本的数据结构,也是语言的核心特性之一。以下是对ECMAScript对象概念的几个关键点总结:

  • 动态性:JavaScript对象是动态的,可以在运行时添加、修改或删除其属性。这为编程提供了极大的灵活性。

  • 原型继承:JavaScript采用原型链继承机制。每个对象都有一个内部的[[Prototype]]属性(可通__proto__访问,尽管不推荐直接操作),指向它的原型对象。当试图访问一个对象的属性或方法时,如果对象本身没有,JavaScript引擎会向上查找其原型链,直至找到或链结束。

  • 构造函数:构造函数是一种特殊的函数,用于初始化新创建的对象。使用new关键字调用构造函数时,会创建一个空对象,并将其[[Prototype]]链接到构造函数的prototype属性所指向的原型对象,然后执行构造函数体内的代码以初始化该对象。

  • 字面量表示法:可以直接使用对象字面量 {} 来创建并初始化一个对象,这是定义简单对象的便捷方式。

  • 属性访问:可以通过.[]操作符访问对象的属性,如 obj.propertyobj['property']

  • 方法:对象的属性可以是函数,这样的属性通常称为方法。方法允许对象封装行为。

  • this关键字:在对象的方法中,this关键字指向调用该方法时的对象上下文。在全局作用域或非严格模式下未明确绑定的函数调用中,this默认指向全局对象(浏览器中是window,Node.js中是globalglobalThis)。

  • 原型对象:每个函数都有一个prototype属性,它指向一个对象,这个对象就是将来新建的对象的原型对象。原型对象上的属性和方法可以被其所有实例共享。

理解JavaScript的对象概念是掌握其面向对象编程的基础,对于编写高效、可维护的代码至关重要。

二、Object 创建对象

创建一个对象,然后给这个对象新建属性和方法。

var car = new Object(); //创建一个Object 对象
car.name = 'AIPHD'; //创建一个name 属性并赋值
car.color = '4AD3FF'; //创建一个color 属性并赋值
car.run = function () { //创建一个run()方法并返回值
return this.name + this.color + '运行中...';
};
alert(car.run()); //输出属性和方法的值

上述代码实例化了一个对象并定义了属性及方法,其中run()方法内部的this关键字即指向car对象自身。但不足之处在于,若需生成多个相似对象,会导致代码重复且冗长。

为了解决多个相似对象实例化的冗余问题,可以采用“工厂模式”,该模式设计初衷正是为了有效减少重复代码,优化实例化过程中的资源消耗。

function createObject(name, age) { //集中实例化的函数
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function () {
return this.name + this.age + '运行中...';
};
return obj;
}
var box1 = createObject('AIPHD', 100); //第一个实例
var box2 = createObject('AIMANT', 200); //第二个实例
alert(box1.run());
alert(box2.run()); //保持独立

尽管工厂模式缓解了重复实例化的问题,但它亦非完美之策。它引发的新挑战包括:为每个对象重复构建相同的属性和方法,导致内存使用低效;以及难以通过类型直接辨别对象函数识别问题等等。

三、构造函数 创建对象

构造函数的使用遵循一套既定的规范,旨在确保代码的高效与可维护性。这些规范主要包括:

  • 命名规范:构造函数名应采用大驼峰命名法,如PersonCar,以便于区分普通函数和构造函数。

  • 首字母大写:遵循惯例,构造函数的名称首字母通常大写,区别于其他小写命名的普通函数。

  • 使用new关键字:调用构造函数时,必须通过new操作符来创建新实例。这会自动执行构造函数内的代码,并为新对象分配内存空间。

  • this关键字:在构造函数内部,this指代新创建的实例对象。可以使用它来给实例添加属性和方法。

  • 无需显式返回值:构造函数默认返回新创建的对象实例,除非使用return语句明确返回一个对象,此时返回的对象将替代默认实例。

  • 原型链继承:利用构造函数的.prototype属性,可以实现方法的共享,避免每个实例都拥有相同方法的副本,从而节省内存。

遵循这些规范,可以编写出结构清晰、易于理解且性能良好的JavaScript代码。

function Car(name, color) { //构造函数模式
this.name = name;
this.color = color;
this.run = function () {
return this.name + this.color + '运行中...';
};
}
var car1 = new Car('AIPHD', '4AD3FF'); //new Car()即可
var car2 = new Car('AIMANT', 'FFF800');
alert(car1.run());
alert(car instanceof Car); //很清晰的识别他从属于Car

构造函数创建对象的过程大致分为以下几个步骤:

  • 调用构造函数:当使用new关键字调用一个构造函数时,JavaScript引擎首先会在内存中创建一个新的空对象。

  • 绑定this:接着,这个新创建的空对象会被绑定到构造函数内部的this关键字上。这意味着通过this可以给新对象添加属性和方法。

  • 执行构造函数体:构造函数的代码体开始执行。在这个阶段,可以通过this给新对象添加属性和方法,比如this.name = 'Alice'

  • 初始化原型:如果构造函数中有对原型(prototype)的修改或扩展(例如,添加共享方法),这些更改会影响之后由该构造函数创建的所有实例。

  • 返回对象:构造函数执行完毕后,如果未显式返回一个对象(或者返回nullundefined),则new操作符会自动返回最初创建的那个对象实例。如果构造函数显式返回一个对象,则返回该对象,而不是默认创建的实例。

通过这一系列步骤,构造函数不仅创建了一个新的对象实例,还为其添加了特定的属性和方法,完成了对象的初始化和配置。

注:

  • 构造函数和普通函数的唯一区别,就是他们调用的方式不同。只不过,构造函数也是函数,必须用new 运算符来调用,否则就是普通函数。

  • this就是代表当前作用域对象的引用。如果在全局范围this 就代表window 对象,如果在构造函数体内,就代表当前的构造函数所声明的对象。

这种方法解决了函数识别问题,但内存消耗问题仍旧存在,且引入了新的困扰:this关键字的上下文不确定性。具体而言,在全局环境中,若作为对象方法调用,this正确指向Box实例;但若以普通函数形式调用,this则默认绑定至全局对象(在浏览器中即window),导致this作用域的混乱。

四、原型模式 创建对象

每个函数自带一个名为prototype的属性,它实质上是一个对象,承载着旨在被该函数构建的所有实例共同继承的属性与方法。从逻辑角度阐释,每当通过某个构造函数生成实例时,该实例会自动指向该构造函数prototype属性所定义的对象,作为其原型。采纳原型模式的意义,在于实现这些共有属性和方法的一次定义、多处复用,无需在每个构造实例时重复定义相同数据,而仅需将这些共享特征附加至原型上即可。

function Car() {} //声明一个构造函数
Car.prototype.name = 'AIPHD'; //在原型里添加属性
Car.prototype.color = '4AD3FF';
Car.prototype.run = function () { //在原型里添加方法
return this.name + this.color + '运行中...';
};

原型设计巧妙地缓解了内存消耗问题,同时也有效应对了this作用域相关挑战。

在创建对象时,我们通常的做法是:将那些在生成每个新实例时需要独立初始化的属性值,放置在构造函数内部定义;而对于那些所有实例共用的方法,则倾向于将其添加到原型(prototype)上。这种方法结合了构造函数与原型的优点,即所谓的“构造函数+原型”混合模式来构建对象。

function Task(id){  
    this.id = id; // 属性(构造函数)
}  
    
Task.prototype.status = "STOPPED";  
Task.prototype.execute = function(args){  // 共用方法(原型)
    return "execute task_"+this.id+"["+this.status+"]:"+args;  
}  
    
var task1 = new Task(1);  
var task2 = new Task(2);  
    
task1.status = "ACTIVE";  
task2.status = "STARTING";  
    
print(task1.execute("task1"));  
print(task2.execute("task2"));

结果:

execute task_1[ACTIVE]:task1
execute task_2[STARTING]:task2

构造器会自动为task1,task2两个对象设置原型对象Task.prototype,这个对象被Task(在此最为构造器)的prototype属性引用,参看下图中的箭头指向。

在这里插入图片描述

Task作为函数实体,其隐含的proto链结点为Function.prototype。同时,系统内置的函数原型(Function.prototype)其proto指向基底的Object.prototype。层层递进,至顶层Object.prototypeproto属性为空(null),标示原型链的顶层终点。

1. 原型对象

在JavaScript中,每个对象均关联一个原型对象,该对象在不同 JavaScript 引擎中的具体实现细节可能有所差异。以Firefox为例,每个对象内部含有一私有属性__proto__,它作为一个指针,指向该对象的原型对象。

2. 原型链

原型链是JavaScript实现继承的核心机制。当试图访问一个对象的属性或方法时,如果该对象本身没有,则JavaScript引擎会向上搜索其原型对象(即__proto__指向的对象)是否有该属性或方法。如果原型对象也没有,引擎会继续在原型的原型对象中寻找,如此层层向上,直到找到该属性或方法,或抵达原型链的末端(通常是Object.prototype的__proto__为null,标志着原型链的结束。这意味着不再有更上一层的原型可供查询,即达到了原型链的顶层)。这一连串由对象及其原型对象逐级连接形成的链式结构,即称为原型链。

2.1. __proto__和 prototype

__proto__是每个JavaScript对象(除了null)都有的一个内部属性,它指向该对象的原型对象(prototype object)。这个属性不是标准的一部分,但在大多数现代浏览器和Node.js环境中都得到了非正式的支持。正式的标准推荐使用Object.getPrototypeOf()和Object.setPrototypeOf()方法来访问和修改对象的原型。

function Animal(name) {
    this.name = name; // 实例属性
}

// 给Animal构造函数的原型添加一个方法
Animal.prototype.speak = function() {
    console.log("My name is " + this.name);
};

// 创建Animal的实例
let cat = new Animal("Tom");

// 访问实例的方法
cat.speak(); // 输出: My name is Tom

// 查看cat的原型链
console.log(cat.__proto__); // 输出: Animal的原型对象,其中包含speak方法
console.log(cat.__proto__ === Animal.prototype); // 输出: true,表明cat的__proto__指向Animal的prototype
console.log(Animal.prototype.__proto__ === Object.prototype) // 输出: true,表明Animal.prototype的__proto__指向创建它的函数对象(Object)的prototype
console.log(Object.prototype.__proto__) // 输出: null,Object.prototype对象也有__proto__属性,但它比较特殊,为null

// 查看Animal构造函数的prototype属性
console.log(Animal.prototype); // 显示包含speak方法的原型对象

我们把这个有__proto__串起来的直到Object.prototype.__proto__为null的链叫做原型链。

2.2. constructor

在JavaScript中,每个构造函数的prototype对象上都有一个默认的属性constructor,这个属性指向构造函数自身。constructor属性的作用主要是为了方便地识别某个实例是通过哪个构造函数创建的,同时也便于从原型对象重新获取构造函数的引用。

  • 自我标识:在复杂的继承结构或者原型链修改后,constructor可以帮助明确对象的构造函数来源,即使原型被覆盖或修改也能追溯到原始构造函数。

  • 便于复用和构造:当需要根据对象类型动态创建新实例时,可以直接通过原型链上的constructor调用构造函数。

function Animal(name) {
    this.name = name;
}

console.log(Animal.prototype.constructor === Animal); // 输出: true,表明constructor指向Animal函数

let cat = new Animal("Kitty");
console.log(cat.constructor === Animal); // 间接通过原型链,同样输出: true

// 即使修改了原型,constructor仍指向正确的构造函数
Animal.prototype = {
    speak: function() {
        console.log("My name is " + this.name);
    }
}; // 注意:这样的直接赋值会丢失原有的constructor属性!

// 修复constructor属性
Animal.prototype.constructor = Animal;

let dog = new Animal("Rex");
console.log(dog.constructor === Animal); // 确保修复后仍为true
Function.prototype.constructor === Function //true
Object.prototype.constructor === Object //true

五、继承机制

ECMAScript(JavaScript)提供了多种继承策略,每种策略都有其特点和适用场景。以下是几种主要的继承方式的详解与示例:

1. 原型链继承

原理:通过让子类型的原型对象等于父类型的实例,使得子类型能够访问到父类型上的属性和方法。

示例:

function SuperType() {
    this.superProperty = true;
}

SuperType.prototype.getSuperValue = function() {
    return this.superProperty;
};

function SubType() {
    this.subProperty = false;
}

// 继承SuperType
SubType.prototype = new SuperType();

// 修复构造函数引用
SubType.prototype.constructor = SubType;

SubType.prototype.getSubValue = function() {
    return this.subProperty;
};

var instance = new SubType();
console.log(instance.getSuperValue()); // 输出: true

2. 构造函数继承(借用构造函数)

原理:在子类型构造函数内部通过callapply方法调用父类型构造函数,为子类型实例添加属性。

示例:

function SuperType(name) {
    this.name = name;
}

function SubType(name, age) {
    SuperType.call(this, name); // 借用构造函数
    this.age = age;
}

var instance = new SubType("Tom", 25);
console.log(instance.name); // 输出: Tom
console.log(instance.age); // 输出: 25

3. 组合继承(原型链+构造函数继承)

原理:结合原型链继承和构造函数继承的优点,既可以在子类型中继承父类型的属性和方法,又能保持每个实例的唯一性。

示例:

function SuperType(name) {
    this.name = name;
}

SuperType.prototype.sayName = function() {
    console.log(this.name);
};

function SubType(name, age) {
    SuperType.call(this, name); // 继承属性
    this.age = age;
}

// 继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType; // 修复构造函数引用

SubType.prototype.sayAge = function() {
    console.log(this.age);
};

var instance = new SubType("Tom", 25);
instance.sayName(); // 输出: Tom
instance.sayAge(); // 输出: 25

4. 寄生式继承

原理:创建一个对象作为父类型的实例,然后为其添加额外的属性和方法,最后返回这个对象。

示例:

function createAnother(original) {
    var clone = Object.create(original); // 或者使用 Object.assign({}, original) 进行浅拷贝
    clone.extraMethod = function() {
        console.log("Extra method");
    };
    return clone;
}

var original = { value: 1 };
var another = createAnother(original);

another.extraMethod(); // 输出: Extra method

5. 寄生组合式继承

原理:结合了寄生式继承和组合继承的特点,优化了组合继承中重复调用父构造函数的问题。

示例:

function inheritPrototype(subType, superType) {
    var prototype = Object.create(superType.prototype); // 创建父类型的原型副本
    prototype.constructor = subType; // 修正构造函数的指向
    subType.prototype = prototype; // 将子类型的原型指向新创建的原型副本
}

function SuperType(name) {
    this.name = name;
}

SuperType.prototype.sayName = function() {
    console.log(this.name);
};

function SubType(name, age) {
    SuperType.call(this, name); // 继承属性
    this.age = age;
}

inheritPrototype(SubType, SuperType); // 实现继承

SubType.prototype.sayAge = function() {
    console.log(this.age);
};

var instance = new SubType("Tom", 25);
instance.sayName(); // 输出: Tom
instance.sayAge(); // 输出: 25

6. ES6 Class继承

原理:ES6引入了class关键字,使得继承更加简洁明了,背后仍然是基于原型继承机制。

示例:

class SuperType {
    constructor(name) {
        this.name = name;
    }
    sayName() {
        console.log(this.name);
    }
}

class SubType extends SuperType {
    constructor(name, age) {
        super(name); // 调用父类构造函数
        this.age = age;
    }
    sayAge() {
        console.log(this.age);
    }
}

let instance = new SubType("Tom", 25);
instance.sayName(); // 输出: Tom
instance.sayAge(); // 输出: 25

每种继承策略各有千秋,开发者应根据实际需求选择最适合的继承方式。ES6的class继承因其简洁易读性,逐渐成为主流选择。

在ECMAScript中运用面向对象技术,关键在于合理设计类与接口,利用ES6的class语法简化继承和封装过程。采用组合而非深度继承提高灵活性,利用 Mixins 引入多重继承特性。重视模块化,合理划分职责,利用闭包和模块模式增强封装性。适时采用原型链继承与构造函数继承,结合实际情况灵活选择,确保代码既高效又易于理解维护。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/586099.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于RK1126的小型化低功耗AI相机,支持人体特征识别、人脸特征识别、案例帽识别等

提供可定制的⼀套 AI相机软硬件开发平台, 硬件采⽤ RockchipRV1126处理器解决 ⽅案,可选择搭配 SonyIMX系列传感器,POE供电与数据传输,采⽤ 38板标准结构设计,快速按需定制外壳,⽀撑从开发到验证到批量⽣产…

基于Matlab使用深度学习的多曝光图像融合

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 在图像处理领域,多曝光图像融合技术是一种重要的技术,它可以将不同曝光条件下…

Ubuntu安装Neo4j

Ubuntu(在线版) 更新软件源 sudo apt-get update 添加Neo4j官方存储库 wget -O - https://debian.neo4j.com/neotechnology.gpg.key | sudo apt-key add - 将地址添加到系统的软件包源列表中 echo deb https://debian.neo4j.com stable latest | su…

update_min_vruntime()流程图

linux kernel scheduler cfs的update_min_vruntime() 看起来还挺绕的。含义其实也简单,总一句话,将 cfs_rq->min_vruntime 设置为: max( cfs_rq->vruntime, min(leftmost_se->vruntime, cfs_rq->curr->vruntime) )。 画个流…

第十四届蓝桥杯国赛:2023次方的思考(指数塔,数论)

首先我们要知道,正常计算的话,指数优先级最高,因此得先计算指数,比如: 2 3 2 512 2^{3^2}512 232512 欧拉定理的关键在于,它允许我们通过减少计算的指数大小来简化模运算。 经过仔细研究(看题…

手写一个uart协议——rs232(未完)

先了解一下关于uart和rs232的基础知识 文章目录 一、RS232的回环测试1.1模块整体架构1.2 rx模块设计1.2.1 波形设计1.2.2代码实现与tb1.2.4 仿真 1.3 tx模块设计1.3.1波形设计 本篇内容: 一、RS232的回环测试 上位机由串口助手通过 rx 线往 FPGA 发 8 比特数据&a…

Qt在任务栏图标和系统托盘图标上显示红点

在任务栏图标上显示红点 关键类&#xff1a;QWinTaskbarButton #include <QWinTaskbarButton>QPointer<QWinTaskbarButton> taskbarBtn nullptr; if (!taskbarBtn) {taskbarBtn new QWinTaskbarButton(window);taskbarBtn->setWindow(window->windowHand…

用C实现通讯录(详细讲解+源码)

前言 &#x1f4da;作者简介&#xff1a;爱编程的小马&#xff0c;正在学习C/C&#xff0c;Linux及MySQL.. &#x1f4da;以后会将数据结构收录为一个系列&#xff0c;敬请期待 ● 本期内容会给大家带来通讯录的讲解&#xff0c;主要是利用结构体来实现通讯录&#xff0c;该通讯…

一周学会Django5 Python Web开发 - Django5 ORM数据库事务

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计50条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

如何给MP3添加专辑封面

MP3的专辑封面可以直接显示在音频播放器上&#xff0c;但如果我们的音乐文件没有专辑封面怎么办&#xff1f;下面来给大家介绍如何添加mp3封面 打开智游剪辑&#xff08;官网&#xff1a;zyjj.cc&#xff09;&#xff0c;搜索音乐封面添加 我们上传一下音乐文件和专辑封面&…

8 聚类算法

目录 0 背景 1 Kmeans 1.1 聚类数量k的确定 2 DBSCAN 2.1 三个点 2.2 算法流程 3 层次聚类 3.1 过程 4 基于分布的聚类:高斯混合模型 0 背景 聚类算法是一种无监督学习技术&#xff0c;用于将数据集中的数据点划分为不同的组或簇&#xff0c;使得同一组内的数据点彼此相…

【微信公众平台】扫码登陆

文章目录 前置准备测试号接口配置 带参数二维码登陆获取access token获取Ticket拼装二维码Url编写接口返回二维码接收扫描带参数二维码事件编写登陆轮训接口测试页面 网页授权二维码登陆生成ticket生成授权地址获取QR码静态文件支持编写获取QR码的接口 接收重定向参数轮训登陆接…

Linux的vim下制作进度条

目录 前言&#xff1a; 回车和换行有区别吗&#xff1f; 回车和换行的区别展示&#xff08;这个我在Linux下演示&#xff09; 为什么会消失呢? 回车和换行的区别 为什么\r和\n产生的效果不同&#xff1f; 打印进度条&#xff1a; &#xff08;1&#xff09;打印字符串 …

【再探】设计模式—抽象工厂及建造者模式

抽象工厂模式和建造者模式都属于创建型模式。两者都能创建对应的对象&#xff0c;而创建者模式更侧重于创建复杂对象&#xff0c;将对象的创建过程封装起来&#xff0c;让客户端不需要知道对象的内部细节。 1 抽象工厂模式 需求&#xff1a; 在使用工厂方法模式时&#xff0…

TCP协议关于速率的优化机制-滑动窗口详解

在上一章中&#xff0c;我们讲述了TCP协议在传输过程中的可靠性http://t.csdnimg.cn/BsImO&#xff0c;这里衔接上一篇文章继续讲&#xff0c;TCP协议的特性&#xff0c;TCP协议写完之后就写&#xff0c;Http和Https等内容吧 1. 滑动窗口 这里的滑动窗口不是指算法里面的双指…

品牌百度百科词条需要什么资料?

品牌百度百科词条是一个品牌的数字化名片&#xff0c;更是品牌历史、文化、实力的全面展现。 作为一个相当拿得出手的镀金名片&#xff0c;品牌百度百科词条创建需要什么资料&#xff0c;今天伯乐网络传媒就来给大家讲解一下。 一、品牌基本信息&#xff1a;品牌身份的明确 品…

用 PyTorch 构建液态神经网络(LNN)

用 PyTorch 构建液态神经网络&#xff08;LNN&#xff09; 文章目录 什么是液态神经网络为什么需要液态神经网络LNN 与 RNN 的区别用 PyTorch 实现 LNNStep 1. 导入必要的库Step 2. 定义网络架构Step 3. 实现 ODE 求解器Step 4. 定义训练逻辑 LNN 的缺陷总结 什么是液态神经网络…

C语言-嵌入式-STM32:FreeRTOS说明和详解

Free即免费的&#xff0c;RTOS的全称是Real time operating system&#xff0c;中文就是实时操作系统。 注意&#xff1a;RTOS不是指某一个确定的系统&#xff0c;而是指一类操作系统。比如&#xff1a;uc/OS&#xff0c;FreeRTOS&#xff0c;RTX&#xff0c;RT-Thread 等这些都…

docker自定义java运行环境镜像

一、下载jre/jdk 压缩包&#xff0c;centos:7基础镜像 1、 下载jdk/dre 下载jdk或jre 官网下载 根据需求下载 jdk:SE Development Kit(开发环境) jre: SE Runtime Environment (运行环境)2、下载centos:7 # 下载centos7 docker镜像 docker pull centos:7#centos查看系统时间 …

面试经典算法题之双指针专题

力扣经典面试题之双指针 ( 每天更新, 每天一题 ) 文章目录 力扣经典面试题之双指针 ( 每天更新, 每天一题 )验证回文串收获 392. 判断子序列 验证回文串 思路 一: 筛选 双指针验证 class Solution { public:bool isPalindrome(string s) {// 所有大写字母 > 小写 去除非字母…