1. 關(guān)於 this 的簡(jiǎn)單介紹
this 關(guān)鍵字是 JavaScript 中最複雜的機(jī)制之一。它是一個(gè)很特別的關(guān)鍵字,被自動(dòng)定義在所有函數(shù)的作用域中。但即使是非常有經(jīng)驗(yàn)的 JavaScript 開(kāi)發(fā)者也很難說(shuō)清它到底指向什麼。
任何足夠先進(jìn)的技術(shù)都和魔法無(wú)異。 — Arthur C. Clarke
實(shí)際上,JavaScript 中this 的機(jī)制並沒(méi)有那麼先進(jìn),但是開(kāi)發(fā)者往往會(huì)把理解過(guò)程複雜化, 毫無(wú)疑問(wèn),在缺乏清晰認(rèn)識(shí)的情況下, this 對(duì)你來(lái)說(shuō)完全就是一種魔法。
2. 為什麼要用 this?
const obj = { title: '掘金', reading() { console.log(this.title + ',一個(gè)幫助開(kāi)發(fā)者成長(zhǎng)的社區(qū)'); } }
this 提供了一種更優(yōu)雅的方式來(lái)隱式「?jìng)鬟f」一個(gè)物件引用,因此可以將 API 設(shè)計(jì)得更加簡(jiǎn)潔並且易於復(fù)用。
隨著你的使用模式越來(lái)越複雜,明確傳遞上下文物件會(huì)讓程式碼變得越來(lái)越混亂,使用 this 則不會(huì)這樣。當(dāng)我們介紹物件和原型時(shí),你就會(huì)明白函數(shù)可以自動(dòng)引用合適的上下文物件有多重要
3. 關(guān)於this 的常見(jiàn)的誤解
人們很容易把this 理解成指向函數(shù)本身,JavaScript 的新手開(kāi)發(fā)者通常會(huì)認(rèn)為,既然把函數(shù)看作一個(gè)物件(JavaScript 中的所有函數(shù)都是物件),那就可以在呼叫函數(shù)時(shí)儲(chǔ)存狀態(tài)(屬性的值)。但結(jié)果通常會(huì)讓他們大吃一驚,例如下面這段程式碼
function foo() { // 讓新添加的 count + 1 this.count++ } // 向函數(shù)對(duì)象 foo 添加了一個(gè)屬性 count foo.count = 0 foo() console.log(foo.count); // 0
這段程式碼看起來(lái)沒(méi)什麼問(wèn)題,但請(qǐng)把目光聚焦到最後一行,輸出foo.count
的結(jié)果竟然是0 ? !
疑問(wèn):為什麼會(huì)這樣?我明明向函數(shù)物件foo
新增了一個(gè)屬性count
,並且函數(shù)內(nèi)部也寫了this.count
,為什麼最後還是0
呢?
解答:因?yàn)?code>this.count 中此時(shí)的this,根本不是指向foo 函數(shù)自身,而是指向全域window
。再細(xì)心一點(diǎn),我們可以發(fā)現(xiàn),在 window
身上,被加入了個(gè) count
屬性,值為 NaN。
(為什麼 this 指向 window 後面會(huì)闡述)
所以,單純的把 this 理解為指向函數(shù)本身是錯(cuò)誤的。
this 實(shí)際上是在函數(shù)被呼叫時(shí)發(fā)生的綁定,它指向什麼完全取決於函數(shù)在哪裡被呼叫。
4. this 的綁定規(guī)則
我們來(lái)看看在函數(shù)的執(zhí)行過(guò)程中呼叫位置如何決定 this 的綁定物件。
找到呼叫位置,然後判斷需要套用下面四條規(guī)則中的哪一條。我首先會(huì)分別解釋 這四條規(guī)則,然後解釋多條規(guī)則都可用時(shí)它們的優(yōu)先順序如何排列。
4.1 預(yù)設(shè)綁定
首先要介紹的是最常用的函數(shù)呼叫類型:獨(dú)立函數(shù)呼叫??梢园堰@條規(guī)則看成是無(wú)法套用其他規(guī)則時(shí)的預(yù)設(shè)規(guī)則。
function foo() { console.log(this.a) } var a = 2 foo() // 2
我們可以看到當(dāng)呼叫
foo()
時(shí),this.a
被解析變成全域變數(shù)a
。為什麼?因?yàn)樵诒纠校?strong>函數(shù)呼叫時(shí)應(yīng)用了this
的預(yù)設(shè)綁定,因此this
指向全域物件。那我們?cè)觞N知道這裡應(yīng)用了預(yù)設(shè)綁定呢?可以透過(guò)分析呼叫位置來(lái)看看
foo()
是如何調(diào) 用的。在程式碼中,foo()
是直接使用不帶任何修飾的函數(shù)參考進(jìn)行呼叫的,因此只能使用預(yù)設(shè)綁定,無(wú)法應(yīng)用其他規(guī)則#這條規(guī)則也解釋了上面count 的程式碼中,為什麼函數(shù)裡面的
this
指向了window
,因?yàn)?code>foo 是屬於獨(dú)立函數(shù)呼叫的,觸發(fā)了預(yù)設(shè)綁定,從而指向全域window。 (瀏覽器中全域是window對(duì)象,node 中是空對(duì)象{})#屬於預(yù)設(shè)綁定規(guī)則的還有:
- 函數(shù)呼叫鏈(一個(gè)函數(shù)又呼叫另外一個(gè)函數(shù))
- 將函數(shù)當(dāng)作參數(shù),傳入到另一個(gè)函數(shù)
(擴(kuò)充:如果使用嚴(yán)格模式( strict mode),則不能將全域物件用於預(yù)設(shè)綁定,因此this 會(huì)綁定到undefined:)
結(jié)論:預(yù)設(shè)綁定的
this
,都指向全域。
4.2 隱式綁定
4.2.1 一般的對(duì)象調(diào)用
這一條需要考慮的規(guī)則是調(diào)用位置是否有上下文對(duì)象,或者說(shuō)是通過(guò)某個(gè)對(duì)象發(fā)起的函數(shù)調(diào)用
function foo() { console.log(this.a) } const obj = { a: 2, foo: foo } // 通過(guò) obj 對(duì)象調(diào)用 foo 函數(shù) obj.foo() // 2
調(diào)用位置會(huì)使用 obj 上下文來(lái)引用函數(shù),因此你可以說(shuō)函數(shù)被調(diào)用時(shí) obj 對(duì)象“擁 有”或者“包含”它。
foo()
被調(diào)用時(shí),它的前面確實(shí)加上了對(duì)obj
的引用。當(dāng)函數(shù)引用有上下文對(duì)象時(shí),隱式綁定規(guī)則會(huì)把函數(shù)調(diào)用中的this
綁定到這個(gè)上下文對(duì)象。因?yàn)檎{(diào)用foo()
時(shí)this
被綁定到obj
上,因此this.a
和obj.a
是一樣的。
4.2.2 對(duì)象屬性引用鏈
對(duì)象屬性引用鏈中只有上一層或者說(shuō)最后一層在調(diào)用位置中起作用。舉例來(lái)說(shuō):
function foo() { console.log(this.a) } var obj2 = { a: 2, foo: foo } var obj1 = { a: 1, obj2: obj2 } obj1.obj2.foo() // 2
最終 this
指向的是 obj2
4.2.3 隱式丟失
一個(gè)最常見(jiàn)的 this 綁定問(wèn)題就是被隱式綁定的函數(shù)會(huì)丟失綁定對(duì)象,也就是說(shuō)它會(huì)應(yīng)用默認(rèn)綁定,從而把 this 綁定到全局對(duì)象或者 undefined 上(取決于是否是嚴(yán)格模式)
第一種情況:將對(duì)象里的函數(shù)賦值給一個(gè)變量
function foo() { console.log(this.a) } var obj = { a: 2, foo: foo } var bar = obj.foo // 函數(shù)別名! var a = 'global' // a 是全局對(duì)象的屬性 bar() // "global"
雖然 bar
是 obj.foo
的一個(gè)引用,但是實(shí)際上,它引用的是 foo
函數(shù)本身,因此此時(shí)的 bar()
其實(shí)是一個(gè)不帶任何修飾的函數(shù)調(diào)用,因此應(yīng)用了默認(rèn)綁定。
第二種情況:傳入回調(diào)函數(shù)時(shí)
function foo() { console.log(this.a) } function doFoo(fn) { // fn 其實(shí)引用的是 foo fn() // <-- 調(diào)用位置! } var obj = { a: 2, foo: foo } var a = 'global' // a 是全局對(duì)象的屬性 doFoo(obj.foo) // "global"
參數(shù)傳遞其實(shí)就是一種隱式賦值,因此我們傳入函數(shù)時(shí)也會(huì)被隱式賦值,所以結(jié)果和上一 個(gè)例子一樣。
結(jié)論:隱式綁定的 this,指向調(diào)用函數(shù)的上下文對(duì)象。
4.3 顯式綁定
4.3.1 使用 call(...) 和 apply(...)
如果我們不想在對(duì)象內(nèi)部包含函數(shù)引用,而想在某個(gè)對(duì)象上強(qiáng)制調(diào)用函數(shù),該怎么做呢?可以使用函數(shù)的 call(..)
和 apply(..)
方法
- JavaScript 提供的絕大多數(shù)函數(shù)以及你自 己創(chuàng)建的所有函數(shù)都可以使用
call(..)
和apply(..)
方法。
這兩個(gè)方法是如何工作的呢?它們的第一個(gè)參數(shù)是一個(gè)對(duì)象,是給 this 準(zhǔn)備的,接著在調(diào)用函數(shù)時(shí)將其綁定到 this。因?yàn)槟憧梢灾苯又付?this 的綁定對(duì)象,因此我們稱之為顯式綁定。 思考以下代碼:
function foo() { console.log(this.a) } var obj = { a: 2 } foo.call(obj) // 2
通過(guò)
foo.call(..)
,我們可以在調(diào)用foo
時(shí)強(qiáng)制把它的this
綁定到obj
上。如果你傳入了一個(gè)原始值(字符串類型、布爾類型或者數(shù)字類型)來(lái)當(dāng)作 this 的綁定對(duì) 象,這個(gè)原始值會(huì)被轉(zhuǎn)換成它的對(duì)象形式(也就是 new String(..)、new Boolean(..) 或者 new Number(..))。這通常被稱為“裝箱”。
從 this 綁定的角度來(lái)說(shuō),call(..) 和 apply(..) 是一樣的,它們的區(qū)別體現(xiàn)在參數(shù)上:第一個(gè)參數(shù)是相同的,后面的參數(shù),call為參數(shù)列表,apply為數(shù)組,他們內(nèi)部的實(shí)現(xiàn)原理也不難理解,詳細(xì)請(qǐng)看以下兩個(gè)手寫方法
4.3.2 硬綁定(一個(gè)函數(shù)總是顯示的綁定到一個(gè)對(duì)象上)
由于硬綁定是一種非常常用的模式,所以 ES5 提供了內(nèi)置的方法 Function.prototype.bind
, 它的用法如下
function foo(num) { console.log(this.a, num) return this.a + num } var obj = { a: 2 } // 調(diào)用 bind() 方法,返回一個(gè)函數(shù) var bar = foo.bind(obj) var b = bar(3) // 2 3 console.log(b) // 5
調(diào)用 bind(...)
方法,會(huì)返回一個(gè)新函數(shù),那么這個(gè)新函數(shù)的 this
,永遠(yuǎn)指向我們傳入的obj
對(duì)象
關(guān)于 bind 方法的簡(jiǎn)單實(shí)現(xiàn),可以前往:手寫 bind 方法,超級(jí)詳細(xì) ???
4.3.3 API調(diào)用的 “上下文(內(nèi)置函數(shù))
第三方庫(kù)的許多函數(shù),以及 JavaScript 語(yǔ)言和宿主環(huán)境中許多新的內(nèi)置函數(shù),都提供了一個(gè)可選的參數(shù),通常被稱為“上下文”(context),其作用和 bind(..)
一樣,確保你的回調(diào)函數(shù)使用指定的 this
。例如:
(1)數(shù)組方法 forEach()
function foo(el) { console.log(el, this.id) } var obj = { id: 'bin' }; [1, 2, 3].forEach(foo, obj) // 輸出: // 1 bin // 2 bin // 3 bin
- 調(diào)用 foo(..) 時(shí)把 this 綁定到 obj 身上
(2)setTimeout()
setTimeout(function() { console.log(this); // window }, 1000);
- 在使用 setTimeout 時(shí)會(huì)傳入一個(gè)回調(diào)函數(shù),而這個(gè)回調(diào)函數(shù)中的
this
一般指向window
,這個(gè)和 setTimeout 源碼的內(nèi)部調(diào)用有關(guān),這個(gè)不再展開(kāi)贅述
結(jié)論:顯式綁定的 this,指向我們指定的綁定對(duì)象。
4.4 new 綁定
在 JavaScript 中,普通函數(shù)可以使用 new
操作符去調(diào)用,此時(shí)的普通函數(shù)則被稱為 “構(gòu)造函數(shù)”。沒(méi)錯(cuò),凡是由 new
操作符調(diào)用的函數(shù),都稱為 “構(gòu)造函數(shù)”
使用 new 來(lái)調(diào)用函數(shù),或者說(shuō)發(fā)生構(gòu)造函數(shù)調(diào)用時(shí),會(huì)自動(dòng)執(zhí)行下面的操作。
在內(nèi)存中創(chuàng)建一個(gè)新對(duì)象。
這個(gè)新對(duì)象內(nèi)部的[[Prototype]] 特性被賦值為構(gòu)造函數(shù)的 prototype 屬性。
構(gòu)造函數(shù)內(nèi)部的this 被賦值為這個(gè)新對(duì)象(即this 指向新對(duì)象)。
執(zhí)行構(gòu)造函數(shù)內(nèi)部的代碼(給新對(duì)象添加屬性)。
如果構(gòu)造函數(shù)返回非空對(duì)象,則返回該對(duì)象;否則,返回剛創(chuàng)建的新對(duì)象。
function foo(a) { this.a = a } var bar = new foo(2) console.log(bar.a) // 2
使用 new
來(lái)調(diào)用 foo(..)
時(shí),我們會(huì)構(gòu)造一個(gè)新對(duì)象并把它綁定到 foo(..)
調(diào)用中的 this
上。new
是最后一種可以影響函數(shù)調(diào)用時(shí) this
綁定行為的方法,我們稱之為 new 綁定。
結(jié)論:new 綁定的 this,都指向通過(guò) new 調(diào)用的函數(shù)的實(shí)例對(duì)象(就是該函數(shù))
5. 綁定規(guī)則的優(yōu)先級(jí)
現(xiàn)在我們已經(jīng)了解了函數(shù)調(diào)用中 this 綁定的四條規(guī)則,你需要做的就是找到函數(shù)的調(diào)用位置并判斷應(yīng)當(dāng)應(yīng)用哪條規(guī)則。但是,如果某個(gè)調(diào)用位置可以應(yīng)用多條規(guī)則呢?所以就需要有綁定規(guī)則的優(yōu)先級(jí)。
它們之間的優(yōu)先級(jí)關(guān)系為:
默認(rèn)綁定 < 隱式綁定 < 顯示綁定(bind) < new綁定
這里提前列出優(yōu)先級(jí),想看詳細(xì)代碼解析的可以往下看,也可以直接拖到最后面的例題部分
5.1 默認(rèn)綁定的優(yōu)先級(jí)最低
毫無(wú)疑問(wèn),默認(rèn)規(guī)則的優(yōu)先級(jí)是最低的,因?yàn)榇嬖谄渌?guī)則時(shí),就會(huì)通過(guò)其他規(guī)則的方式來(lái)綁定this
5.2 隱式綁定和顯式綁定的優(yōu)先級(jí)比較
測(cè)試一下即可知道,有以下代碼:
function foo() { console.log(this.a) } var obj1 = { a: 1, foo: foo } var obj2 = { a: 2, foo: foo } // 同時(shí)使用隱式綁定和顯示綁定 obj1.foo.call(obj2) // 2
可以看到,輸出的結(jié)果為 2,說(shuō)明 foo
函數(shù)內(nèi) this
指向的是 obj2
,而 obj2 是通過(guò)顯示綁定調(diào)用的,所以:顯示綁定的優(yōu)先級(jí)更高
5.3 隱式綁定和 new 綁定的優(yōu)先級(jí)比較
有以下測(cè)試代碼:
function foo() { console.log(this); } var obj = { title: "juejin", foo: foo } // 同時(shí)使用隱式綁定和new綁定 new obj.foo(); // foo對(duì)象
最后 foo
函數(shù)輸出的 this
為 foo 對(duì)象,說(shuō)明new綁定優(yōu)先級(jí)更高(否則應(yīng)該輸出 obj 對(duì)象),所以:new 綁定的優(yōu)先級(jí)更高
5.4 new 綁定和顯示綁定的優(yōu)先級(jí)比較
最后,new 綁定和顯式綁定誰(shuí)的優(yōu)先級(jí)更高呢?
new綁定和call、apply是不允許同時(shí)使用的,只能和 bind 相比較,如下:
function foo() { console.log(this) } var obj = { title: "juejin" } var foo = new foo.call(obj); // 直接報(bào)錯(cuò)
但是 new 綁定可以和 bind 方法返回后的函數(shù)一起使用
function foo() { console.log(this); } var obj = { title: "juejin" } var bar = foo.bind(obj); var foo = new bar(); // foo 對(duì)象, 說(shuō)明使用的是new綁定
最后 foo
函數(shù)輸出的 this
為 foo 對(duì)象,說(shuō)明new綁定優(yōu)先級(jí)更高(否則應(yīng)該輸出 obj 對(duì)象),所以:new 綁定的優(yōu)先級(jí)更高
優(yōu)先級(jí)結(jié)論:默認(rèn)綁定 < 隱式綁定 < 顯示綁定(bind)< new綁定
6. 判斷this
現(xiàn)在我們可以根據(jù)優(yōu)先級(jí)來(lái)判斷函數(shù)在某個(gè)調(diào)用位置應(yīng)用的是哪條規(guī)則??梢园凑障旅娴?順序來(lái)進(jìn)行判斷:
函數(shù)是否在 new 中調(diào)用(new 綁定)?如果是的話 this 綁定的是新創(chuàng)建的對(duì)象。 var bar = new foo()
函數(shù)是否通過(guò) call、apply(顯式綁定)或者硬綁定調(diào)用?如果是的話,this 綁定的是 指定的對(duì)象。 var bar = foo.call(obj2)
函數(shù)是否在某個(gè)上下文對(duì)象中調(diào)用(隱式綁定)?如果是的話,this 綁定的是那個(gè)上 下文對(duì)象。 var bar = obj1.foo()
如果都不是的話,使用默認(rèn)綁定。如果在嚴(yán)格模式下,就綁定到 undefined,否則綁定 到全局對(duì)象。 var bar = foo()
就是這樣。對(duì)于正常的函數(shù)調(diào)用來(lái)說(shuō),理解了這些知識(shí)你就可以明白 this 的綁定原理了。 不過(guò)……凡事總有例外
7. 綁定例外
規(guī)則總有例外,這里也一樣。在某些場(chǎng)景下 this 的綁定行為會(huì)出乎意料,你認(rèn)為應(yīng)當(dāng)應(yīng)用其他綁定規(guī)則時(shí),實(shí)際上應(yīng)用的可能是默認(rèn)綁定規(guī)則。
7.1 箭頭函數(shù)
箭頭函數(shù)不使用 this 的四種標(biāo)準(zhǔn)規(guī)則,而是根據(jù)外層(函數(shù)或者全局)作用域來(lái)決定 this。
7.2 被忽略的this
如果你把 null 或者 undefined 作為 this 的綁定對(duì)象傳入 call、apply 或者 bind,這些值在調(diào)用時(shí)會(huì)被忽略,實(shí)際應(yīng)用的是默認(rèn)綁定規(guī)則:
function foo() { console.log(this.a) } var a = 2 foo.call(null) // 2 foo.call(undefined) // 2 foo.bind(null)();
最后輸出的結(jié)果都是 2,說(shuō)明 this
指向的是全局 window
7.3 間接引用
另一個(gè)需要注意的是,你有可能(有意或者無(wú)意地)創(chuàng)建一個(gè)函數(shù)的間接引用,在這種情況下,調(diào)用這個(gè)函數(shù)會(huì)應(yīng)用默認(rèn)綁定規(guī)則。 間接引用最容易在賦值時(shí)發(fā)生:
function foo() { console.log(this.a) } var a = 2 var o = { a: 3, foo: foo } var p = { a: 4 } o.foo(); // 3 // 函數(shù)賦值 (p.foo = o.foo)() // 2
賦值表達(dá)式 p.foo = o.foo
的返回值是目標(biāo)函數(shù)的引用,因此調(diào)用位置是 foo()
屬于獨(dú)立函數(shù)調(diào)用,而不是 p.foo()
或者 o.foo()
。根據(jù)我們之前說(shuō)過(guò)的,這里會(huì)應(yīng)用默認(rèn)綁定。
8. this 判斷例題
請(qǐng)說(shuō)出例題中的輸出結(jié)果
8.1 例題一
var name = "window"; var person = { name: "person", sayName: function () { console.log(this.name); } }; function sayName() { var sss = person.sayName; sss(); person.sayName(); (person.sayName)(); (b = person.sayName)(); } sayName();
解析:
function sayName() { var sss = person.sayName; // 獨(dú)立函數(shù)調(diào)用,沒(méi)有和任何對(duì)象關(guān)聯(lián) sss(); // window // 關(guān)聯(lián) person.sayName(); // person (person.sayName)(); // person (b = person.sayName)(); // window }
8.2 例題二
var name = 'window' var person1 = { name: 'person1', foo1: function () { console.log(this.name) }, foo2: () => console.log(this.name), foo3: function () { return function () { console.log(this.name) } }, foo4: function () { return () => { console.log(this.name) } } } var person2 = { name: 'person2' } person1.foo1(); person1.foo1.call(person2); person1.foo2(); person1.foo2.call(person2); person1.foo3()(); person1.foo3.call(person2)(); person1.foo3().call(person2); person1.foo4()(); person1.foo4.call(person2)(); person1.foo4().call(person2);
解析:
// 隱式綁定,肯定是person1 person1.foo1(); // person1 // 隱式綁定和顯示綁定的結(jié)合,顯示綁定生效,所以是person2 person1.foo1.call(person2); // person2 // foo2()是一個(gè)箭頭函數(shù),不適用所有的規(guī)則 person1.foo2() // window // foo2依然是箭頭函數(shù),不適用于顯示綁定的規(guī)則 person1.foo2.call(person2) // window // 獲取到foo3,但是調(diào)用位置是全局作用于下,所以是默認(rèn)綁定window person1.foo3()() // window // foo3顯示綁定到person2中 // 但是拿到的返回函數(shù)依然是在全局下調(diào)用,所以依然是window person1.foo3.call(person2)() // window // 拿到foo3返回的函數(shù),通過(guò)顯示綁定到person2中,所以是person2 person1.foo3().call(person2) // person2 // foo4()的函數(shù)返回的是一個(gè)箭頭函數(shù) // 箭頭函數(shù)的執(zhí)行找上層作用域,是person1 person1.foo4()() // person1 // foo4()顯示綁定到person2中,并且返回一個(gè)箭頭函數(shù) // 箭頭函數(shù)找上層作用域,是person2 person1.foo4.call(person2)() // person2 // foo4返回的是箭頭函數(shù),箭頭函數(shù)只看上層作用域 person1.foo4().call(person2) // person1
9. 總結(jié)
如果要判斷一個(gè)運(yùn)行中函數(shù)的 this 綁定,就需要找到這個(gè)函數(shù)的直接調(diào)用位置。找到之后就可以順序應(yīng)用下面這四條規(guī)則來(lái)判斷 this 的綁定對(duì)象。
由 new 調(diào)用?綁定到新創(chuàng)建的對(duì)象。
由 call 或者 apply(或者 bind)調(diào)用?綁定到指定的對(duì)象。
由上下文對(duì)象調(diào)用?綁定到那個(gè)上下文對(duì)象。
默認(rèn):在嚴(yán)格模式下綁定到 undefined,否則綁定到全局對(duì)象。
每文一句:如果把生活比喻為創(chuàng)作的意境,那么閱讀就像陽(yáng)光。
ok,本次的分享就到這里,如果本章內(nèi)容對(duì)你有所幫助的話可以點(diǎn)贊+收藏,希望大家都能夠有所收獲。有任何疑問(wèn)都可以在評(píng)論區(qū)留言,大家一起探討、進(jìn)步!
【推薦學(xué)習(xí):javascript高級(jí)教程】
以上是帶你去詳解 this 的四個(gè)綁定規(guī)則的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費(fèi)脫衣圖片

Undresser.AI Undress
人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強(qiáng)大的PHP整合開(kāi)發(fā)環(huán)境

Dreamweaver CS6
視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版
神級(jí)程式碼編輯軟體(SublimeText3)

WebSocket與JavaScript:實(shí)現(xiàn)即時(shí)監(jiān)控系統(tǒng)的關(guān)鍵技術(shù)引言:隨著互聯(lián)網(wǎng)技術(shù)的快速發(fā)展,即時(shí)監(jiān)控系統(tǒng)在各個(gè)領(lǐng)域中得到了廣泛的應(yīng)用。而實(shí)現(xiàn)即時(shí)監(jiān)控的關(guān)鍵技術(shù)之一就是WebSocket與JavaScript的結(jié)合使用。本文將介紹WebSocket與JavaScript在即時(shí)監(jiān)控系統(tǒng)中的應(yīng)用,並給出程式碼範(fàn)例,詳細(xì)解釋其實(shí)作原理。一、WebSocket技

如何使用WebSocket和JavaScript實(shí)現(xiàn)線上語(yǔ)音辨識(shí)系統(tǒng)引言:隨著科技的不斷發(fā)展,語(yǔ)音辨識(shí)技術(shù)已成為了人工智慧領(lǐng)域的重要組成部分。而基於WebSocket和JavaScript實(shí)現(xiàn)的線上語(yǔ)音辨識(shí)系統(tǒng),具備了低延遲、即時(shí)性和跨平臺(tái)的特點(diǎn),成為了廣泛應(yīng)用的解決方案。本文將介紹如何使用WebSocket和JavaScript來(lái)實(shí)現(xiàn)線上語(yǔ)音辨識(shí)系

如何利用JavaScript和WebSocket實(shí)現(xiàn)即時(shí)線上點(diǎn)餐系統(tǒng)介紹:隨著網(wǎng)路的普及和技術(shù)的進(jìn)步,越來(lái)越多的餐廳開(kāi)始提供線上點(diǎn)餐服務(wù)。為了實(shí)現(xiàn)即時(shí)線上點(diǎn)餐系統(tǒng),我們可以利用JavaScript和WebSocket技術(shù)。 WebSocket是一種基於TCP協(xié)定的全雙工通訊協(xié)議,可實(shí)現(xiàn)客戶端與伺服器的即時(shí)雙向通訊。在即時(shí)線上點(diǎn)餐系統(tǒng)中,當(dāng)使用者選擇菜餚並下訂單

JavaScript和WebSocket:打造高效的即時(shí)天氣預(yù)報(bào)系統(tǒng)引言:如今,天氣預(yù)報(bào)的準(zhǔn)確性對(duì)於日常生活以及決策制定具有重要意義。隨著技術(shù)的發(fā)展,我們可以透過(guò)即時(shí)獲取天氣數(shù)據(jù)來(lái)提供更準(zhǔn)確可靠的天氣預(yù)報(bào)。在本文中,我們將學(xué)習(xí)如何使用JavaScript和WebSocket技術(shù),來(lái)建立一個(gè)高效的即時(shí)天氣預(yù)報(bào)系統(tǒng)。本文將透過(guò)具體的程式碼範(fàn)例來(lái)展示實(shí)現(xiàn)的過(guò)程。 We

如何使用WebSocket和JavaScript實(shí)現(xiàn)線上預(yù)約系統(tǒng)在當(dāng)今數(shù)位化的時(shí)代,越來(lái)越多的業(yè)務(wù)和服務(wù)都需要提供線上預(yù)約功能。而實(shí)現(xiàn)一個(gè)高效、即時(shí)的線上預(yù)約系統(tǒng)是至關(guān)重要的。本文將介紹如何使用WebSocket和JavaScript來(lái)實(shí)作一個(gè)線上預(yù)約系統(tǒng),並提供具體的程式碼範(fàn)例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進(jìn)行全雙工

JavaScript教學(xué):如何取得HTTP狀態(tài)碼,需要具體程式碼範(fàn)例前言:在Web開(kāi)發(fā)中,經(jīng)常會(huì)涉及到與伺服器進(jìn)行資料互動(dòng)的場(chǎng)景。在與伺服器進(jìn)行通訊時(shí),我們經(jīng)常需要取得傳回的HTTP狀態(tài)碼來(lái)判斷操作是否成功,並根據(jù)不同的狀態(tài)碼來(lái)進(jìn)行對(duì)應(yīng)的處理。本篇文章將教你如何使用JavaScript來(lái)取得HTTP狀態(tài)碼,並提供一些實(shí)用的程式碼範(fàn)例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹(shù)中插入一個(gè)新的節(jié)點(diǎn)。這個(gè)方法需要兩個(gè)參數(shù):要插入的新節(jié)點(diǎn)和參考節(jié)點(diǎn)(即新節(jié)點(diǎn)將要插入的位置的節(jié)點(diǎn))。

JavaScript中的HTTP狀態(tài)碼取得方法簡(jiǎn)介:在進(jìn)行前端開(kāi)發(fā)中,我們常常需要處理與後端介面的交互,而HTTP狀態(tài)碼就是其中非常重要的一部分。了解並取得HTTP狀態(tài)碼有助於我們更好地處理介面?zhèn)骰氐馁Y料。本文將介紹使用JavaScript取得HTTP狀態(tài)碼的方法,並提供具體程式碼範(fàn)例。一、什麼是HTTP狀態(tài)碼HTTP狀態(tài)碼是指當(dāng)瀏覽器向伺服器發(fā)起請(qǐng)求時(shí),服務(wù)
