V少JS基础班之第七弹

文章目录

    • 一、 前言
    • 二、本节涉及知识点
    • 三、重点内容
          • 1、prototype
          • 2、constructor
          • 3、中场回顾&总结
          • 4、__ proto__
          • 5、第二次中场回顾&总结
          • 6、原型链
          • 6、第三次中场回顾&总结
          • 7、原型链中的奇点

一、 前言

第七弹内容是原型链。网络上原型链的资料很多。但是我看了很多篇,每次看完就觉得懂了,过了一段时间又迷糊了起来。总结了一下,大部分时候我们都是靠背诵而不是理解他。
现在只是将自己对原型链的理解和大家进行交流。 如果有其他看法,欢迎留言。
本系列为一周一更,计划历时6个月左右。从JS最基础【变量与作用域】到【异步编程,密码学与混淆】。希望自己能坚持下来, 也希望给准备入行JS逆向的朋友一些帮助, 我现在脸皮厚度还行。先要点赞,评论和收藏。也是希望如果本专栏真的对大家有帮助可以点个赞,有建议或者疑惑可以在下方随时问。
先预告一下【V少JS基础班】的全部内容,我做了一些调整。看着很少,其实,正儿八经细分下来其实挺多的,第一个月的东西也一点不少。
第一个月【变量作用域BOMDOM数据类型操作符
第二个月【函数闭包原型链、this】
第三个月【面向对象编程、 异步编程、nodejs】
第四个月【密码学、各类加密函数】
第五个月【jsdom、vm2、express】
第六个月【基本请求库、前端知识对接】

==========================================================

二、本节涉及知识点

原型链

==========================================================

三、重点内容

想要了解原型链,首先我们得知道什么是原型。 但是如果我们直接讲原型,初学者基本上不能一次就吸收 。那我们就从为什么要使用原型开始。

我们要学习原型链必须得先知道什么是构造函数。而且还需要了解闭包,对象和this。如果不清楚可以看我之前js基础班的文章。

本章的全部内容均在js的标准模式下讨论。不考虑非标准(严格)模式

如果想要知道自己原型链有没有掌握直接翻到文章最末尾,如果能完全理解那些等式,说明原型链已经掌握。如果有疑问,对照目录查看有疑问的部分。

1、prototype

我们还是从简单的开始。

首先原型和继承是相关联的,但是我们还没有开始学习面向对象,那我们就从闭包开始。 第六弹的闭包中我们有讲过闭包的作用。 那我们再复习一下闭包。
我们先用看一个例子:

function createCounter() {let privateCounter = 0;function changeBy(val) {privateCounter += val;}return {increment() {changeBy(1);},decrement() {changeBy(-1);},value() {return privateCounter;},};
}const c1 = createCounter();
const c2 = createCounter();

这是一个典型的闭包案例。 函数increment和getCount都使用了外部变量count。如果大家对闭包有疑问可以看一下我的第六弹闭包的讲解。
那我们继续说。 闭包虽然私有化了变量。但是他有个致命的缺点就是,我们每次const一个 counter。都会创建一个独立的空间。 如果我们创建100个counter。
那我就有100个increment空间。对于一门语言来说,这样的设计结构是致命的。 那有没有什么办法解决这个问题呢。 当然是有的。我们可以单独创建一个空间用于存储。
那就是我们今天需要学习的原型(prototype)。

什么原型(取自MDN):

Every JavaScript function has a prototype property that is used when the function is used as a constructor with the new keyword. The prototype property is an object that is shared among all instances created by that constructor.When a new object is created using a constructor function, the new object’s internal [[Prototype]] (i.e., its __proto__) is set to the constructor’s prototype object.This means that all instances inherit properties and methods defined on the constructor’s prototype.

翻译:

每个JavaScript函数都有一个原型属性,当该函数用作带有new关键字的构造函数时,会使用该属性。原型属性是一个在该构造函数创建的所有实例之间共享的对象。
当使用构造函数创建新对象时,新对象的内部[[Prototype]](即其__proto__)被设置为构造函数的原型对象。
这意味着所有实例都继承了构造函数原型上定义的属性和方法。

OS:

首先第一点。 所有的对象(null除外)都有一个[[prototype]]的内置原型
(它其实是一个对象,我们称之为原型对象。即构造函数.prototype)。它不是一个传统的键值对,而是一个继承引用。 我们不可以使用.或者[]的形式去调用它。 但是我们可以用两个方法去查找它,一个是__proto__方法,这个是非官方的接口,还有一个是getprototypeof方法,这个是ES6的官方接口。 这两个方法是等价的,具体如下:p_1.__proto__ === Object.getPrototypeOf(p_1) === Person.prototype。

好,到了这里就已经听不懂了。 那我们就先丢弃这么多概念。 虽然我们还未学习到面向对象,但是这里不得不用一个面向对象的概念来解释一下了。
如果我要new一个特定的对象出来, 比如一个person。 他有name属性,age属性,同时他还有一个说话的方法。 我们的闭包是不是就不太实用了?因为每次使用闭包我们私有化属性的时候,他总会占用一个私有的空间。
那我们为了节约内存就需要一个共享的空间, 我们所有new出来的对象,不共用的属性用自己的空间比如:name和age,而可以共用的方法就共享一个空间比如这个say。 那我们用什么方法呢。 那就是原型 prototype

如果没有原型, 我们的写法是怎样:

function Person(name, age) {this.name = name;this.age = age;this.say = function(words) {console.log(`${this.name} says: ${words}`);};
}

这个代码确实可以实现say方法, 但是我们看一下他们的地址

const p1 = new Person('Sean', 30);
const p2 = new Person('Tom', 28);console.log(p1.say === p2.say); // false,两个 say 是不同的函数

那如果我们使用了原型,会是怎么样的

function Person(name, age) {this.name = name;this.age = age;
}
Person.prototype.say = function(words) {console.log(`${this.name} says: ${words}`);
};const p1 = new Person('Sean', 30);
const p2 = new Person('Tom', 28);console.log(p1.say === p2.say); // true,共享一个 say 方法
现在我们大概有了概念了。 Person.prototype 是一个Person函数指向的“容器”,我们把想要共享的方法存放到这个“容器”中。 
那只要是由我们 Person 构造函数 new出来的对象,都能使用这个“容器”里的方法。这就是我们prototype的作用。 

好。 这里我们应该就了解了原型【prototype】了。 那我们来具体看看这个原型是什么东西。 同样的代码。
在这里插入图片描述
我们这里很明显的看到。 Person.prototype 它是一个对象。 我们称之为原型对象。 每一个构造函数都有一个原型对象。 它用于提供所有由该构造函数创建的实例共享的方法和属性。
到这里,我们应该完全能理解prototype吧。ok, 对于原型prototype,这里有以下几点需要补充。

1- 所有的构造函数都有原型 prototype。 甚至可以这么说,除了箭头函数,所有的函数都有原型 prototype。
这点应该很好理解, 普通函数,可以使用new方法调用,从而成为一个构造函数。 所以,只要能使用new的函数,都应该有一个prototype。 我们只用记住,只要一个函数,他能被new, 那它必有一个原型。只是,原型里存不存放共享属性和方法。
在这里插入图片描述
示例如上。 如果我们在Person中的原型上添加一个say方法,那这个say方法就是Person所有实例共享的方法。 而go中的原型未挂载任何方法。

2- 原型对象是构造函数的一个属性, 他是挂载在构造函数上的一个方法,是一个对象。
至此,我们已经学习到了原型链中的三分之一。 请记住这个链条:
在这里插入图片描述
好的, 到此,我们已经学会了原型。 我们接下来看一下构造函数 constructor

2、constructor

我们看下MDN的原文

A constructor is a specialized function that generates objects with the same shape and behavior. 
The constructor initializes this object with some data specific to the object. 
The concept of a constructor can be applied to most object-oriented programming languages.In JavaScript, a constructor is usually declared within a class, but it can also be declared as a function. In fact, 
any function that can be called with the new operator is a constructor.

翻译:

构造函数是生成具有相同形状和行为的对象的专用函数。构造函数使用特定于该对象的一些数据初始化该对象。
构造函数的概念可以应用于大多数面向对象的编程语言。

os:

在JavaScript中,构造函数通常在类中声明,但也可以声明为函数。事实上,
任何可以用new运算符调用的函数都是构造函数。

光读这句话我们就已经了解了constructor。 他就是一个构造函数。我们还是用上面的示例,直接看这个等式
Person.prototype.constructor === Person
很好理解,Person的原型对象的构造函数是Person。
这个也非常好理解。 至此原型链我们已经学完了三分之二。 还剩下最后一个 __ proto__
在这里插入图片描述

3、中场回顾&总结

到这里大家应该都还能接受。 那我们趁现在总结一波。 让大家加深印象。看以下两句话:

1- 构造函数的原型就是原型对象
2- 原型对象的构造函数就是构造函数
猛地一看,说了两句废话。仔细一看,没错这就是废话。
那我们就可以看看这个图解了。逻辑清晰,毫无异议
图1:
在这里插入图片描述
图2:
在这里插入图片描述
图3:
在这里插入图片描述
好。 到此我们都毫无异议。下面就到了重头戏了。 __ proto__

4、__ proto__

好, 那我们看一下最绕的一个知识点 __ proto__。 __ proto__到底是个什么。 我们看MDN中的原文。
第一句:

proto is an accessor property (a getter function and a setter function) that exposes the internal [[Prototype]] (either null or an
object) of an object through which it inherits properties.

翻译:

__proto__是一个访问器属性(getter函数和setter函数),它公开了对象的内部[[Prototype]](null或对象),通过它继承属性。

第二句:

The proto property of an object is used to access or set the
prototype (i.e., the internal [[Prototype]] property) of the object.
It is not recommended to use proto in your code, but it is widely
supported and often used in examples or for debugging purposes.

翻译:

对象的__proto__属性用于访问或设置对象的原型(即内部[[prototype]]属性)。不建议在代码中使用__proto__,但它得到了广泛的支持,经常用于示例或调试目的。

好, 我们直接理解它。__ proto__是一个访问属性。 如同 get和setter函数一样。 他用于访问 [[prototype]] 属性。 原则上,这个是个非官方接口。 我们不应该用在官方渠道。 但是因为在ES6之前没有官方接口,它作为第三方家口应用广泛,大家都普遍在使用。 所以,原则上不同意但是默认了这个用法。

他的官方接口是这个:

Object.setPrototypeOf(rabbit, animal);
Object.getPrototypeOf(rabbit); // returns animal

所以之后如果看到 getPrototypeOf 我们应该知道,他等同于 __ proto__.

在这里,提到了 [[prototype]] 属性。 其实这才是原型链的核心。 我们继续看MDN中的原文

[[Prototype]] The [[Prototype]] of an object is the object it inherits
methods and properties from. This is a “hidden” or “internal” property
— it is not directly accessible in code, although modern JavaScript
environments expose it via proto, or through
Object.getPrototypeOf() and Object.setPrototypeOf().

When trying to access a property of an object, if the property is not
found directly on the object, JavaScript looks up the chain through
the object’s prototype, and the prototype’s prototype, and so on,
until it finds a match or reaches the end of the chain (null).

好的, 概念够多了。 我直接口语话讲解

1- __ proto__是指向[[prototype]]的方法。
他是一个非官方接口。 我们之所以用它,是因为我们无法直接访问 [[prototype]] (我称之为隐藏原型)

2- 在js中,所有的对象都有[[prototype]](之后我会称之为隐藏原型),除了由Object.create(null)构建的对象。
js中Object.create(null)构建的对象除外。 所有的对象都有隐藏原型。 我们都可以使用__ proto__去查看他的隐藏原型。

3- [[prototype]]和prototype的区别在于服务对象不同
我们知道prototype是构造函数的原型对象。 他是构造函数的公开属性,可以直接Person.prototype访问。 而 [[prototype]]是针对对象的隐藏属性,不可以直接访问,需要使用__ proto__或者Object.getPrototypeof去指向这个属性。

4- 我们查看[[prototype]] 隐藏原型永远只考虑指向问题,而不是是否等于
原型链适用于实现继承的属性。 我们不能用 .或者[] 等方式去查找他,而是使用__ proto__或者Object.getPrototypeof去指向它。

总结:(重要,很重要,非常重要重要)

以上4条一定要牢记。 [[prototype]]是原型链的关键。 我们不要以属性调用的方式去思考隐藏原型。因为它不是包含在对象的属性中,而是对象的内部槽(internal slot),它提供了一个可以搜索的地址指针。

5、第二次中场回顾&总结

ok。 到此,我们已经完全掌握了原型链中的三要素。 prototype,constructor, __ proto__。 我们的学习进度已经到了80% 。 看上去都是如此简单,为什么原型链却被称为一道坎呢。那就是我们接下来要看的链式结构了, 我希望大家是理解了这个链式结构而不是盲目的背下来。
我们看一下没有原型链之前,是这样。

在这里插入图片描述
有了原型链是这样

在这里插入图片描述

好, 原型链我们已经学完了基础三件套,进度完成了80%。接下来我们看一下原型链最后的20%。

6、原型链

我们现在知道了,原型链的核心在 [[prototype]]这个隐藏原型。 我们接下来的讨论不考虑Object.create(null)
回顾一下我们今天学习的原型。 实例对象由构造函数构造而成。而为了私有化属性,并且在不额外占用资源的情况下,我们引入了prototype原型的概念,我们需要将共享的属性挂在prototype这个原型上, 实现了对象间继承。

我们引入了构造函数的 prototype 原型对象的概念。为了节约内存、实现方法复用,我们通常将所有实例需要共享的方法挂在构造函数的 prototype 上,从而让所有通过 new 创建的对象都能通过原型链访问这些共享成员,这就是 JavaScript 实现对象间继承的基础机制。

除了我们自定义的属性和方法之外,每个函数或对象还拥有一些内置的属性或方法,比如函数的 name、length、arguments
等。这些并不是来自我们手动添加的 prototype,而是来源于 JavaScript 引擎内部构建的更高层级的原型链继承,比如:

所有函数(包括构造函数)本质都是由 Function 构造出来的,因此它们继承自 Function.prototype

所有对象最终都继承自 Object.prototype,这是原型链的顶端

所以,不论是自定义属性,还是内置属性,它们的可访问性都依赖于原型链的查找机制。

核心:

那这些属性究竟都来自哪里呢?我们需要记住一个核心规律:
无论是我们手动创建的原型对象,还是内置构造函数的原型对象,它们最终都会通过原型链继承自 Object.prototype。

换句话说,Object.prototype 是 JavaScript 中所有原型链的终点(根对象),它定义了一些通用的方法,例如
toString()、hasOwnProperty() 等。正因为所有对象最终都会继承自它,这些方法才可以在任意对象上被调用。

这就是 JavaScript 中“原型链继承”的终极奥义:所有对象的 [[Prototype]](隐藏原型)最终都会指向
Object.prototype,除非你用 Object.create(null) 显式跳过这个链条。

ok, 又是一大堆的概念。 如果大家看概念无感,我直接口语翻译一下(请不要跟我的口语化较真,口语只是方便你理解,准确信息查看上述概念)。

os口语表达:
我们可以这么理解,我们所有的原型都来自于 Object.prototyp.它长下面这个样子。
在这里插入图片描述

Object.prototype 是 JavaScript 中所有对象原型链的终点。它本身定义了一些最基础的方法和属性,比如 toString()、valueOf()、hasOwnProperty() 等。

只要不人为破坏原型链,或者不使用 Object.create(null) 显式创建一个“无原型”的对象,任何你创建的对象最终都会继承自 Object.prototype。

正因为如此,这些基础方法在所有对象上都可用。例如:

const obj = { name: 'Sean' };
console.log(obj.hasOwnProperty('name')); // true 来自 Object.prototype

因此,Object.prototype 承载着 JavaScript 对象系统的“公共祖先角色”。它定义的行为就像“遗传基因”,被所有对象默认继承,除非你手动断开这条继承链。

正如我们示例:

function Person(name, age) {this.name = name;this.age = age;
}
Person.prototype.say = function(words) {console.log(`${this.name} says: ${words}`);
};
p1 = new Person('zhangsan', 18)function go() {console.log('普通函数')
}

p1作为实例对象, 他的隐藏原型是Person.prototype。 而Person.prototype的隐藏原型是Object.prototype。 如图:
在这里插入图片描述

6、第三次中场回顾&总结

1- 至此我们就掌握了10%。 我们再次回顾一下。
2- prototype,是原型对象,准确的说是构造函数的原型对象。 它是一个属性。
3- constructor,是构造函数, 他是原型对象的构造函数, 他是一个函数对象。
4- __ proto__: 是一个非官方的第三方接口, 他用于查找[[prototype]]这个隐藏原型
5- 所有对象都有隐藏原型,隐藏原型的终点是 Object.prototype (Object.prototype的隐藏原型是null)

好的, 我们原型链已经掌握了90%了。 到此,应该没有不懂的地方吧。 我们继续最后的10%

7、原型链中的奇点

我们早在之前函数的讲解中说过了。 在js中函数是个特殊的对象。 那构造函数也应该是个对象。 那当我们查找构造函数的隐藏原型时,是不是应该按照构造函数的原型去查找呢。 比如实例对象p1的构造函数是Person。Person的原型是Person.prototype.而Person.prototype的隐藏原型是Object.prototype。

我们p1的隐藏原型是Person.prototype, Person.prototype 的隐藏原型是Object.prototype。 这完全没问题。

但是,我们查找Person这个构造函数的隐藏原型的时候,却不是Person.prototype。 原型对象和隐藏原型是不同的。p1是由构造函数Person对应的原型Person.prototype继承来的。

而Person这个构造函数, 他是继承于Function.prototype
记住:
所有的函数的隐藏原型都是 Function.prototype

os口语总结:
我们学习原型链不要看哪个属性等于谁, 而要看它继承于谁。 这里我们要知道。 构造函数Person,他是通过Function这个构造函数new出来的。 所有的函数,都是通过Function new出来的。 所以, 他们的隐藏原型永远是指向Function.prototype。 这点应该很好理解。

如果无法理解,请对照对象的继承。 所有的对象,都继承自Object。 他们的隐藏原型最终都指向Object.prototype。 不是因为谁等于谁,而是因为Object创造了所有对象,所以,对象的隐藏原型才指向它。 同理,Function创造了所有函数。

我们原型链最后一个奇点就是:
Function他作为构造函数,他的隐藏原型是 Function.prototype

Function.__proto__ === Function.prototype

因为只要是函数, 他都继承于Function.prototype。 包括Object()。

ok, 到此。 大家已经完全掌握了原型链。

最后我们做一下练习题。 自己对照浏览器查看答案

1. Function.prototype == Object.__proto__
2. Function.prototype.constructor == Function
3. (1).__proto__.constructor == Number
4. Object.prototype == Object. __proto__
5. Function.__proto__ == Function.prototype
6. ('1').__proto__.constructor == String
7. Function.prototype == Function.constructor
8. Function.prototype == Function.constructor.prototype
9. Number.prototype.__proto__ == Object.prototype
10.  var a={}; a.constructor.prototype == a.__proto__
1. Function.constructor == Object.constructor
2.  (new Object) .__proto__ == Object.prototype
3. Set.__proto__ ==  Symbol.__proto__
4. Symbol.prototype.__proto__ ==  Object.prototype
5. (1).__proto__ == Number.prototype
6.  Number.prototype.__proto__ ==  Object.prototype
7. Object.prototype.__proto__ == Function.prototype.__proto__
8. (1).__proto__.__proto__.constructor == Object
9. (1).__proto__.constructor.constructor == Object.constructor

原型链之所以绕,是因为我们之前一直以谁是谁,谁等于谁的角度去看。但我们以继承的想法去理解之后,就会发现原型链就是那么清晰。 比如我们将练习题拿出来翻译:

第一题

Function.prototype == Object.__proto__

Object函数的隐藏原型是不是Function的原型对象。 答案是肯定的。 我们说过任何函数他都继承Function的原型对象。 所有的函数都是Function new出来的

第二题

Function.prototype.constructor == Function

Function的原型对象的构造函数是不是Function。这就是一句废话。构造函数的原型对象的构造函数,可不就是他自己吗。 原型对象不懂就去看prototype。构造函数不懂就去看constructor

后面的题目大家自己看, 翻译成口语话,说出来,就有很明显的感知。

有点啰嗦,脑壳要炸。原型链文章写得有点久,总想讲清楚一点,但是翻来覆去就那么几句话。
如有问题,私信。 最后求一波点赞收藏。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nuxt3自动打包及自动修改端口号脚本

Nuxt3自动打包及自动修改端口号脚本技术文章大纲 背景与需求 Nuxt3作为现代Vue框架,开发中常需处理打包部署和端口配置问题。自动化脚本可提升效率,减少手动操作错误。 实现自动打包 利用Nuxt3内置命令结合Node.js脚本实现自动化构建。通过npm run build…

红海云国资案例之多层级工贸集团的一体化HR平台建设实战

在中国经济迈向高质量发展的进程中,国有企业作为重要的经济支柱和行业引领者,正面临着数字化转型的深刻变革。F集团作为G市首家实现工贸一体化运营的大型企业,位列中国轻工业百强,其在人力资源数字化转型中的探索和实践&#xff0…

TCP详解——流量控制、滑动窗口

目录 流量控制 滑动窗口 丢包重传 情况一:数据到达,应答丢失 情况二:数据包丢失 流量控制 TCP协议会根据接收端的缓冲区大小来调整发送速度,剩余空间多则发送速度快,否则降低发送速度 接收端将⾃⼰可以接收的缓…

C#高级特性面试问题的详细分析,涵盖核心概念、应用场景和最佳实践

序列化与反序列化 1. 什么是序列化和反序列化?用途是什么? // 序列化示例 Person person new Person { Name "Alice", Age 30 }; string json JsonSerializer.Serialize(person); // 序列化为JSON// 反序列化示例 Person deserialized Js…

【电脑】内存的基础知识

内存(Memory)是计算机中用于临时存储数据和程序的地方,它直接影响到系统的运行速度和性能。以下是关于内存的详细知识:1. 内存类型常见的内存类型包括以下几个主要种类:SDRAM (Synchronous Dynamic Random Access Memo…

Java---IDEA

IDEA概述 IDEA:全称Intellij IDEA,是用于Java语言开发的集成开发环境 集成环境:把代码编写,编译,运行,调试等多种功能综合到一起的开发工具 下载与安装 下载:IntelliJ IDEA – the IDE for …

【每日刷题】x 的平方根

69. x 的平方根 - 力扣(LeetCode) 方法一:暴力 从0开始遍历,直到 ans*ans > x 为止,这时ans-1就是答案。需要注意可能会爆int,所以ans要开为long,最后再转换为int。 class Solution {publ…

C#元组:从基础到实战的全方位解析

C#元组:从基础到实战的全方位解析 在 C# 编程中,元组(Tuple)是一种轻量级的数据结构,用于临时存储多个不同类型的元素。无论是方法返回多个值、LINQ 查询中的临时投影,还是简化数据传递,元组都以…

Django母婴商城项目实践(二)

2、母婴商城项目环境配置 环境配置: Python3.12 解释器Pycharm Professional 2025.1 编辑器Django 4.2(或 Django 5.x)MySQL 8.0.28 数据库 1、Django框架 介绍 Django是一个高级的Python Web应用框架,可以快速开发安全和可维护的网站。由经验丰富的开发者构建,Django负责…

Go语言的Channel通道的含义。区分缓冲通道和非缓冲通道,并讨论通道的发送、接收、关闭以及如何安全地从已关闭的通道读取数据。

非缓冲通道:非缓冲通道在确定时没有声明容量大小,发送和接收操作会同步阻塞,直到另一端准备好。发送方和接收方必须同时就绪才能完成数据交换,否则会阻塞。常用于goroutine之间的同步通信。缓冲通道:缓冲通道在确定时就…

tensor

😉如果您想用jupyter notebook跑我的笔记,可以在下面获取ipynb版本 😊麻烦给个免费的star😘 ❤️主包也更建议这种形式,上面的笔记也更加全面,每一步都有直观的输出 文章目录📚 PyTorch张量操作…

STM32-DAC数模转换

DAC数模转换:将数字信号转换成模拟信号特性:2个DAC转换器每个都拥有一个转换通道8位或12位单调输出(8位右对齐;12位左对齐右对齐)双ADC通道同时或者分别转换外部触发中断电压源控制部分(外部触发3个APB1&am…

前后端集合如何传递

前端vue后端rest风格&#xff1a;1.路径传参&#xff08;参数必传&#xff09;&#xff0c;通过pathvarible注解后端&#xff1a;DeleteMapping("/{YYIDs}")public R<Void> remove(NotEmpty(message "主键不能为空")PathVariable String[] YYIDs) {…

1353. 最多可以参加的会议数目

1353. 最多可以参加的会议数目 题目链接&#xff1a;1353. 最多可以参加的会议数目 代码如下&#xff1a; class Solution { public:int maxEvents(vector<vector<int>>& events) {int mx 0;for (auto& e : events) {mx max(mx, e[1]); // 找到最大的结…

OCR 本地版本

UMI OCR 支持本地部署&#xff0c;支持HTTP OCR

大数据驱动的酒店用品需求预测模型研究 开发——毕业论文,毕业设计——仙盟创梦IDE

主页酒店用品 平台协议促销毕业论文摘要本研究旨在构建基于大数据分析的酒店用品需求预测模型&#xff0c;以提高酒店用品批发企业的库存管理效率和供应链响应速度。研究整合了酒店历史采购数据、季节因素、市场趋势、节假日信息等多源数据&#xff0c;通过对比传统时间序列模型…

Windows11桌面解锁守护脚本

使用python程序加bat一键运行脚本&#xff0c;妈妈再也不用担心我的电脑桌面了import os import time import cv2 import pyautogui import psutil from datetime import datetimeclass UnlockMonitor:def __init__(self):"""初始化监控器"""sel…

Linux Ubuntu系统的用户管理

一.关于root用户默认我们安装完系统后 注册的用户就是管理员用户标识符 $ 管理员标识符#最高管理员在Ubuntu系统中,root是最高管理员,拥有最大的权限,默认情况下root用户没有启用密码,而是通过sudo机制来获取管理员权限二.Ubuntu系统中root用户的默认状态root用户存在,但未启用…

ROS1学习第三弹

ROS1学习第二弹 本文纯属记录学习过程&#xff0c;所学教程来自B站古月居ROS入门21讲 tf工具的使用 命令行中 1.rosrun tf view_frames 生成当前各个坐标的结构图&#xff0c;导出pdf文件到当前终端所在文件夹下面2.rosrun rviz rviz -d rospackage find turtle_tf /rviz/tu…

技术演进中的开发沉思-30 MFC系列:五大机制

MFC&#xff0c;记得我刚毕业时在 CRT 显示器前敲下第一行 MFC 代码时&#xff0c;那时什么都不懂&#xff0c;没有框架的概念。只觉得眼前的 CObject 像位沉默且复杂的大家族&#xff0c; 就像老北京胡同里的大家族&#xff0c;每个门牌号都藏着自己的故事。但现在看看&#x…