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
英文地址,請注明出處:http://en.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…