日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

詳解JavaScript的this指向和綁定

瀏覽:203日期:2023-10-15 09:21:28

注意: 本文屬于基礎(chǔ)篇,請大神繞路。如果你不夠了解,或者了解的還不完整,那么可以通過本文來復(fù)習(xí)一下。

this 指向的類型

剛開始學(xué)習(xí) JavaScript 的時(shí)候,this 總是最能讓人迷惑,下面我們一起看一下在 JavaScript 中應(yīng)該如何確定 this 的指向。

this 是在函數(shù)被調(diào)用時(shí)確定的,它的指向完全取決于函數(shù)調(diào)用的地方,而不是它被聲明的地方(除箭頭函數(shù)外)。當(dāng)一個(gè)函數(shù)被調(diào)用時(shí),會創(chuàng)建一個(gè)執(zhí)行上下文,它包含函數(shù)在哪里被調(diào)用(調(diào)用棧)、函數(shù)的調(diào)用方式、傳入的參數(shù)等信息,this 就是這個(gè)記錄的一個(gè)屬性,它會在函數(shù)執(zhí)行的過程中被用到。

this 在函數(shù)的指向有以下幾種場景:

作為構(gòu)造函數(shù)被 new 調(diào)用 作為對象的方法使用 作為函數(shù)直接調(diào)用 被 call、apply、bind 調(diào)用 箭頭函數(shù)中的 this

下面我們分別來討論一下這些場景中 this 的指向。

1.new 綁定

函數(shù)如果作為構(gòu)造函數(shù)使用 new 調(diào)用時(shí), this 綁定的是新創(chuàng)建的構(gòu)造函數(shù)的實(shí)例。

function Foo() { console.log(this)}var bar = new Foo() // 輸出: Foo 實(shí)例,this 就是 bar

實(shí)際上使用 new 調(diào)用構(gòu)造函數(shù)時(shí),會依次執(zhí)行下面的操作:

創(chuàng)建一個(gè)新對象 構(gòu)造函數(shù)的 prototype 被賦值給這個(gè)新對象的 __proto__ 將新對象賦給當(dāng)前的 this 執(zhí)行構(gòu)造函數(shù) 如果函數(shù)沒有返回其他對象,那么 new 表達(dá)式中的函數(shù)調(diào)用會自動返回這個(gè)新對象,如果返回的不是對象將被忽略

2.顯式綁定

通過 call、apply、bind 我們可以修改函數(shù)綁定的 this,使其成為我們指定的對象。通過這些方法的第一個(gè)參數(shù)我們可以顯式地綁定 this。

function foo(name, price) { this.name = name this.price = price}function Food(category, name, price) { foo.call(this, name, price) // call 方式調(diào)用 // foo.apply(this, [name, price]) // apply 方式調(diào)用 this.category = category}new Food(’食品’, ’漢堡’, ’5塊錢’)// 瀏覽器中輸出: {name: '漢堡', price: '5塊錢', category: '食品'}

call 和 apply 的區(qū)別是 call 方法接受的是參數(shù)列表,而 apply 方法接受的是一個(gè)參數(shù)數(shù)組。

func.call(thisArg, arg1, arg2, ...) // call 用法func.apply(thisArg, [arg1, arg2, ...]) // apply 用法

而 bind 方法是設(shè)置 this 為給定的值,并返回一個(gè)新的函數(shù),且在調(diào)用新函數(shù)時(shí),將給定參數(shù)列表作為原函數(shù)的參數(shù)序列的前若干項(xiàng)。

func.bind(thisArg[, arg1[, arg2[, ...]]]) // bind 用法

舉個(gè)例子:

var food = { name: ’漢堡’, price: ’5塊錢’, getPrice: function (place) { console.log(place + this.price) },}food.getPrice(’KFC ’) // 瀏覽器中輸出: 'KFC 5塊錢'var getPrice1 = food.getPrice.bind({ name: ’雞腿’, price: ’7塊錢’ }, ’肯打雞 ’)getPrice1() // 瀏覽器中輸出: '肯打雞 7塊錢'

關(guān)于 bind 的原理,我們可以使用 apply 方法自己實(shí)現(xiàn)一個(gè) bind 看一下:

// ES5 方式Function.prototype.bind = Function.prototype.bind || function () { var self = this var rest1 = Array.prototype.slice.call(arguments) var context = rest1.shift() return function () { var rest2 = Array.prototype.slice.call(arguments) return self.apply(context, rest1.concat(rest2)) } }// ES6 方式Function.prototype.bind = Function.prototype.bind || function (...rest1) { const self = this const context = rest1.shift() return function (...rest2) { return self.apply(context, [...rest1, ...rest2]) } }

ES6 方式用了一些 ES6 的知識比如 rest 參數(shù)、數(shù)組解構(gòu)。

注意: 如果你把 null 或 undefined 作為 this 的綁定對象傳入 call、apply、bind,這些值在調(diào)用時(shí)會被忽略,實(shí)際應(yīng)用的是默認(rèn)綁定規(guī)則。

var a = ’hello’function foo() { console.log(this.a)}foo.call(null) // 瀏覽器中輸出: 'hello'

3.隱式綁定

函數(shù)是否在某個(gè)上下文對象中調(diào)用,如果是的話 this 綁定的是那個(gè)上下文對象。

var a = ’hello’var obj = { a: ’world’, foo: function () { console.log(this.a) },}obj.foo() // 瀏覽器中輸出: 'world'

上面代碼中,foo 方法是作為對象的屬性調(diào)用的,那么此時(shí) foo 方法執(zhí)行時(shí),this 指向 obj 對象。也就是說,此時(shí) this 指向調(diào)用這個(gè)方法的對象,如果嵌套了多個(gè)對象,那么指向最后一個(gè)調(diào)用這個(gè)方法的對象:

var a = ’hello’var obj = { a: ’world’, b: { a: ’China’, foo: function () { console.log(this.a) }, },}obj.b.foo() // 瀏覽器中輸出: 'China'

最后一個(gè)對象是 obj 上的 b,那么此時(shí) foo 方法執(zhí)行時(shí),其中的 this 指向的就是 b 對象。

4.默認(rèn)綁定

函數(shù)獨(dú)立調(diào)用,直接使用不帶任何修飾的函數(shù)引用進(jìn)行調(diào)用,也是上面幾種綁定途徑之外的方式。非嚴(yán)格模式下 this 綁定到全局對象(瀏覽器下是 winodw,node 環(huán)境是 global),嚴(yán)格模式下 this 綁定到 undefined (因?yàn)閲?yán)格模式不允許 this 指向全局對象)。

var a = ’hello’function foo() { var a = ’world’ console.log(this.a) console.log(this)}foo() // 相當(dāng)于執(zhí)行 window.foo()// 瀏覽器中輸出: 'hello'// 瀏覽器中輸出: Window 對象

上面代碼中,變量 a 被聲明在全局作用域,成為全局對象 window 的一個(gè)同名屬性。函數(shù) foo 被執(zhí)行時(shí),this 此時(shí)指向的是全局對象,因此打印出來的 a 是全局對象的屬性。

注意有一種情況:

var a = ’hello’var obj = { a: ’world’, foo: function () { console.log(this.a) },}var bar = obj.foobar() // 瀏覽器中輸出: 'hello'

此時(shí) bar 函數(shù),也就是 obj 上的 foo 方法為什么又指向了全局對象呢,是因?yàn)?bar 方法此時(shí)是作為函數(shù)獨(dú)立調(diào)用的,所以此時(shí)的場景屬于默認(rèn)綁定,而不是隱式綁定。這種情況和把方法作為回調(diào)函數(shù)的場景類似:

var a = ’hello’var obj = { a: ’world’, foo: function () { console.log(this.a) },}function func(fn) { fn()}func(obj.foo) // 瀏覽器中輸出: 'hello'

參數(shù)傳遞實(shí)際上也是一種隱式的賦值,只不過這里 obj.foo 方法是被隱式賦值給了函數(shù) func 的形參 fn,而之前的情景是自己賦值,兩種情景實(shí)際上類似。這種場景我們遇到的比較多的是 setTimeout 和 setInterval,如果回調(diào)函數(shù)不是箭頭函數(shù),那么其中的 this 指向的就是全局對象.

其實(shí)我們可以把默認(rèn)綁定當(dāng)作是隱式綁定的特殊情況,比如上面的 bar(),我們可以當(dāng)作是使用 window.bar() 的方式調(diào)用的,此時(shí) bar 中的 this 根據(jù)隱式綁定的情景指向的就是 window。

this 綁定的優(yōu)先級

this 存在多個(gè)使用場景,那么多個(gè)場景同時(shí)出現(xiàn)的時(shí)候,this 到底應(yīng)該如何指向呢。這里存在一個(gè)優(yōu)先級的概念,this 根據(jù)優(yōu)先級來確定指向。優(yōu)先級:new 綁定 > 顯示綁定 > 隱式綁定 > 默認(rèn)綁定

所以 this 的判斷順序:

new 綁定: 函數(shù)是否在 new 中調(diào)用?如果是的話 this 綁定的是新創(chuàng)建的對象; 顯式綁定: 函數(shù)是否是通過 bind、call、apply 調(diào)用?如果是的話,this 綁定的是指定的對象; 隱式綁定: 函數(shù)是否在某個(gè)上下文對象中調(diào)用?如果是的話,this 綁定的是那個(gè)上下文對象; 如果都不是的話,使用默認(rèn)綁定。如果在嚴(yán)格模式下,就綁定到 undefined,否則綁定到全局對象。

箭頭函數(shù)中的 this

箭頭函數(shù) 是根據(jù)其聲明的地方來決定 this 的,它是 ES6 的知識點(diǎn)。

箭頭函數(shù)的 this 綁定是無法通過 call、apply、bind 被修改的,且因?yàn)榧^函數(shù)沒有構(gòu)造函數(shù) constructor,所以也不可以使用 new 調(diào)用,即不能作為構(gòu)造函數(shù),否則會報(bào)錯(cuò)。

var a = ’hello’var obj = { a: ’world’, foo: () => { console.log(this.a) },}obj.foo() // 瀏覽器中輸出: 'hello'

我們可以看看 ECMAScript 標(biāo)準(zhǔn)中對箭頭函數(shù)的描述。

原文:

An Arrow Function does not define local bindings for arguments, super, this, or new.target. Any reference to arguments, super, this, or new.target within an ArrowFunction must resolve to a binding in a lexically enclosing environment. Typically this will be the Function Environment of an immediately enclosing function.

翻譯:

箭頭函數(shù)不為 arguments、super、this 或 new.target 定義本地綁定。箭頭函數(shù)中對 arguments、super、this 或 new.target 的任何引用都解析為當(dāng)前所在詞法作用域中的綁定。通常,這是箭頭函數(shù)所在的函數(shù)作用域。

— ECMAScript Language Specification - Arrow Function | ECMA 標(biāo)準(zhǔn) - 箭頭函數(shù)

一個(gè) this 的小練習(xí)

用一個(gè)小練習(xí)來實(shí)戰(zhàn)一下:

var a = 20var obj = { a: 40, foo: () => { console.log(this.a) function func() { this.a = 60 console.log(this.a) } func.prototype.a = 50 return func },}var bar = obj.foo() // 瀏覽器中輸出: 20bar() // 瀏覽器中輸出: 60new bar() // 瀏覽器中輸出: 60

稍微解釋一下:

1)var a = 20 這句在全局變量 window 上創(chuàng)建了個(gè)屬性 a 并賦值為 20;

2)首先執(zhí)行的是 obj.foo(),這是一個(gè)箭頭函數(shù),箭頭函數(shù)不創(chuàng)建新的函數(shù)作用域直接沿用語句外部的作用域,因此 obj.foo() 執(zhí)行時(shí)箭頭函數(shù)中 this 是全局 window,首先打印出 window 上的屬性 a 的值 20,箭頭函數(shù)返回了一個(gè)原型上有個(gè)值為 50 的屬性 a 的函數(shù)對象 func 給 bar;

3)繼續(xù)執(zhí)行的是 bar(),這里執(zhí)行的是剛剛箭頭函數(shù)返回的閉包 func,其內(nèi)部的 this 指向 window,因此 this.a 修改了 window.a 的值為 60 并打印出來;

4)然后執(zhí)行的是 new bar(),根據(jù)之前的表述,new 操作符會在 func 函數(shù)中創(chuàng)建一個(gè)繼承了 func 原型的實(shí)例對象并用 this 指向它,隨后 this.a = 60 又在實(shí)例對象上創(chuàng)建了一個(gè)屬性 a,在之后的打印中已經(jīng)在實(shí)例上找到了屬性 a,因此就不繼續(xù)往對象原型上查找了,所以打印出第三個(gè) 60。

如果把上面例子的箭頭函數(shù)換成普通函數(shù)呢,結(jié)果會是什么樣?

var a = 20var obj = { a: 40, foo: function () { console.log(this.a) function func() { this.a = 60 console.log(this.a) } func.prototype.a = 50 return func },}var bar = obj.foo() // 瀏覽器中輸出: 40bar() // 瀏覽器中輸出: 60new bar() // 瀏覽器中輸出: 60

這個(gè)例子就不詳細(xì)講解了。

如果把上面兩個(gè)例子弄懂原理,基本上 this 的指向就掌握的差不多啦~

以上就是詳解JavaScript的this指向和綁定的詳細(xì)內(nèi)容,更多關(guān)于JavaScript的this指向和綁定的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
精品国产精品久久一区免费式| 综合亚洲自拍| 欧美精品国产一区| 日韩av影院| 日韩二区三区四区| 欧美日韩午夜电影网| 青青伊人久久| 国产精品欧美大片| 国产精品蜜月aⅴ在线| 国产精品成人3p一区二区三区| 国产精品流白浆在线观看| 国产日产高清欧美一区二区三区| 日韩一区二区三区在线看| 亚洲精品女人| 奇米色欧美一区二区三区| 欧美久久亚洲| 91欧美精品| 国产精品22p| 国产一区二区三区久久久久久久久| 色婷婷综合网| 香蕉久久99| 免费人成黄页网站在线一区二区| 亚洲日本国产| 久久99久久久精品欧美| 高清一区二区三区av| 久久精品91| 国产农村妇女精品一二区| 日本国产欧美| 麻豆精品新av中文字幕| 日韩在线观看不卡| 妖精视频成人观看www| 婷婷精品久久久久久久久久不卡| 日韩一区网站| 卡一卡二国产精品| 日本精品影院| 免费久久99精品国产| 日韩一区二区三区高清在线观看 | 久久av免费| 精品国产不卡一区二区| 久久网站免费观看| 日韩激情中文字幕| 福利片在线一区二区| 亚洲欧洲一区二区天堂久久| 欧美天堂在线| 日韩综合精品| 亚洲一区区二区| 国产精品片aa在线观看| 成人自拍av| 日本亚洲最大的色成网站www| 欧美国产不卡| 欧美日韩精品免费观看视频完整| 男女激情视频一区| 国产精品视频一区二区三区四蜜臂 | 三级欧美在线一区| 国产欧美日韩免费观看| 精品久久在线| 欧美一级一区| 欧美日韩国产在线一区| 欧美亚洲国产一区| 日韩黄色大片| 一区视频在线| 日本精品在线播放| 97精品在线| 蜜桃av一区二区三区电影| 麻豆视频观看网址久久| 日韩视频二区| 麻豆国产精品| 久久国产精品99国产| 国产精品99一区二区三| 亚洲午夜免费| 欧美激情综合| 日韩午夜一区| 国产91欧美| 欧美一区二区三区久久精品| 久久久久久久久久久妇女| 91伊人久久| 欧美一级专区| 91精品久久久久久久久久不卡| 日韩成人一级| 99成人在线| 婷婷激情一区| 鲁大师精品99久久久| 一区二区国产精品| 欧美日韩一二三四| 成人在线免费观看91| 视频一区欧美精品| 久久国产日韩| 日韩av在线播放网址| 国产亚洲久久| 蜜桃av一区二区三区电影| 亚洲网站视频| 在线一区av| 久久只有精品| 日本va欧美va欧美va精品| 在线视频精品| 香蕉久久99| 久久九九电影| 欧美香蕉视频| 美女精品久久| 国产高清亚洲| 免费成人在线观看| 99视频在线精品国自产拍免费观看| 日本不良网站在线观看| 久久一区国产| 国产精品va| 国产日韩在线观看视频| 日韩成人一级| 亚洲精品看片| 日韩精品一二区| 久久xxxx| 男人操女人的视频在线观看欧美| 欧美特黄a级高清免费大片a级| 日本一二区不卡| 一本一道久久a久久精品蜜桃| 成人午夜精品| 日韩一级不卡| 91成人超碰| 国产乱码精品一区二区亚洲| 中文字幕成人| 日产精品一区二区| 91成人在线| 麻豆理论在线观看| 在线视频精品| 日韩欧美三区| 免费不卡在线观看| 日韩精品成人在线观看| 国产亚洲久久| 日本不卡视频在线| 亚州精品视频| 每日更新成人在线视频| 999精品色在线播放| 免费观看不卡av| 亚洲综合二区| 四虎精品永久免费| 激情91久久| 日韩免费福利视频| 国产传媒在线| 免费人成在线不卡| 国产69精品久久| 日本不卡一二三区黄网| 日韩高清在线不卡| 久久久成人网| 欧美精品国产白浆久久久久| 亚洲手机在线| 少妇精品久久久一区二区三区| 久久国产三级| 日韩中文字幕一区二区三区| 午夜欧美精品久久久久久久| 日韩**一区毛片| 日韩欧美三级| 天堂资源在线亚洲| 亚洲aa在线| 国产精品igao视频网网址不卡日韩| 精品99久久| 欧洲激情综合| 国产精品久久久一区二区| 少妇精品导航| 91欧美极品| 亚洲激情中文| 国产精品白丝久久av网站| 91亚洲一区| 日韩高清欧美激情| 日韩深夜视频| 日韩欧美三区| 欧美日韩色图| 麻豆视频久久| 亚洲ww精品| japanese国产精品| 久久免费视频66| 亚洲综合小说| 九九在线精品| 国产在线看片免费视频在线观看| 午夜在线视频观看日韩17c| av资源亚洲| 国产精品嫩草影院在线看| 国产成人精品免费视| 蜜臀久久99精品久久一区二区| 日韩va亚洲va欧美va久久| 日韩中文首页| 精品72久久久久中文字幕| 亚洲丝袜啪啪| 国产精品久久| 精品资源在线| 日韩精品一区二区三区中文字幕| 日本午夜大片a在线观看| 少妇精品久久久一区二区三区| 免费日韩成人| 国产精品99免费看| 久久精品国产999大香线蕉 | 久久国产日本精品| 天堂а√在线最新版中文在线| 五月天久久网站| 国产精品99精品一区二区三区∴ | 亚洲精品一二三区区别| 国产精品三级| 欧美极品中文字幕| 亚洲国产成人精品女人| 亚洲毛片网站| 国产精品1区| 国产激情久久|