JavaScript this綁定與this指向問題的解析
一、this 綁定
怎么理解 this?
其實(shí) this 就是一個(gè)指針,它指示的就是當(dāng)前的一個(gè)執(zhí)行環(huán)境,可以用來(lái)對(duì)當(dāng)前執(zhí)行環(huán)境進(jìn)行一些操作。
MDN 解釋:在絕大多數(shù)情況下,函數(shù)的調(diào)用方式?jīng)Q定了 this 的值(運(yùn)行時(shí)綁定)。this 不能在執(zhí)行期間被賦值,并且在每次函數(shù)被調(diào)用時(shí) this 的值也可能會(huì)不同。ES5 引入了 bind 方法來(lái)設(shè)置函數(shù)的 this 值,而不用考慮函數(shù)如何被調(diào)用的。ES2015 引入了箭頭函數(shù),箭頭函數(shù)不提供自身的 this 綁定(this 的值將保持為閉合詞法上下文的值)。
this 是如何綁定的?
每個(gè)函數(shù)的 this 是在調(diào)用時(shí)被綁定的,完全取決于函數(shù)的調(diào)用位置。我們找到函數(shù)的調(diào)用位置,然后運(yùn)用以下四種綁定規(guī)則來(lái)判斷函數(shù)的 this 指向。
1、默認(rèn)綁定
函數(shù)的 this 會(huì)默認(rèn)綁定到全局對(duì)象 window 上,如果在嚴(yán)格模式中,this 綁定到 undefined。
function foo (){ console.log(this.a) } let a = 1 foo() // 1
2、隱式綁定
調(diào)用位置是否有上下文對(duì)象,或者被某個(gè)對(duì)象擁有或包含。
function foo(){ console.log(this.a) } let obj = { a: 2, foo:foo } let a = 1 obj.foo(); // 2 function foo(){ console.log(this.a) } let obj1 = { a: 2, foo: foo } let obj2 = { a: 3, obj1: obj1 } let a = 1 obj2.obj1.foo(); // 2
3、顯式綁定
直接改變 this 指向,綁定到另一個(gè)執(zhí)行環(huán)境
function foo(){ console.log(this.a) } let obj = { a: 1 } foo.call(obj)
4、new 綁定
new 出來(lái)的函數(shù) this 綁定的是新創(chuàng)建的對(duì)象
function Foo(a){ this.a = a } let bar = new Foo(2) console.log(bar.a) // 2
this 綁定優(yōu)先級(jí)
默認(rèn)綁定的優(yōu)先級(jí)是最低的
new 綁定 > 顯式綁定 > 隱式綁定 > 默認(rèn)綁定
1、顯示綁定 VS 隱式綁定
function foo(){ console.log(this.a) } let obj1 = { a: 1, foo: foo } let obj2 = { a: 2 } console.log(obj1.foo()) // 1 obj1.foo.call(obj2) // 2
通過(guò)以上代碼我們可以看到 顯式綁定 的優(yōu)先級(jí)高于 隱式綁定
2、顯示綁定 VS new 綁定
function foo(a){ this.a = a } let obj1 = { foo } let bar = foo.bind(obj1) bar(2) console.log(obj1.a) // 2 let bar2 = new bar(3) console.log(obj1.a) // 2 console.log(bar2.a) // 3
new 修改了顯示綁定 調(diào)用 bar 中的 this,所以 new 綁定的優(yōu)先級(jí)高于顯式綁定
二、this 指向
判斷準(zhǔn)則
第一準(zhǔn)則:this 永遠(yuǎn)指向函數(shù)運(yùn)行時(shí)所在的對(duì)象,而不是函數(shù)被創(chuàng)建時(shí)所在的對(duì)象。(不包含箭頭函數(shù))
第二準(zhǔn)則:無(wú)論是否在嚴(yán)格模式下,在全局執(zhí)行環(huán)境中(在任何函數(shù)體外部)this 都指向全局對(duì)象。
判斷順序
- 函數(shù)是否在 new 中調(diào)用,如果是的話 this 綁定的是新創(chuàng)建的對(duì)象;
- 函數(shù)是否通過(guò) call、apply、bind 的方式調(diào)用,如果是的話 this 綁定的是指定的對(duì)象;
- 函數(shù)是否在某個(gè)上下文中被調(diào)用,如果是的話 this 綁定的是函數(shù)調(diào)用的上下文;
- 除此之外 this 綁定的就是全局對(duì)象 在嚴(yán)格模式下綁定的是 undefined。
常見的指向問題
- 箭頭函數(shù)沒有自己的 this 指針(需要從執(zhí)行上下文來(lái)進(jìn)行判斷)
三、改變 this 指向
有四種方式
- 變量保存 this:將 this 臨時(shí)保存下來(lái)
- call():使用一個(gè)指定的 this 值和單獨(dú)給出的一個(gè)或多個(gè)參數(shù)來(lái)調(diào)用一個(gè)函數(shù)。
- bind():會(huì)有一個(gè)返回值,返回值是一個(gè)擁有第一個(gè)函數(shù)作用域的新的函數(shù)體
- apply():調(diào)用一個(gè)具有給定 this 值的函數(shù),以及以一個(gè)數(shù)組(或一個(gè)類數(shù)組對(duì)象)的形式提供的參數(shù)。
變量保存 this
var _this = window; var obj = { name:"張三", show:function(){ console.log(this) //obj console.log(_this) // window } } obj.show()
call
call() 方法使用一個(gè)指定的 this 值和單獨(dú)給出的一個(gè)或多個(gè)參數(shù)來(lái)調(diào)用一個(gè)函數(shù)。
函數(shù)名稱.bind(參數(shù)1,參數(shù)2,a,b,c.....)
參數(shù)1:當(dāng)前函數(shù)的作用域
參數(shù)2:需要傳遞的參數(shù),參數(shù)是一個(gè)一個(gè)傳
function fn(a,b){ console.log(this,a,b) } document.onclick = functioin(){ fn.call(document,1,2) }
可以使用 call 來(lái)實(shí)現(xiàn)繼承:寫一個(gè)方法,然后讓另外一個(gè)新的對(duì)象來(lái)繼承它(而不是在新對(duì)象中再寫一次這個(gè)方法)。
function Product(name, price) { this.name = name; this.price = price; } function Food(name, price) { Product.call(this, name, price); this.category = 'food'; } function Toy(name, price) { Product.call(this, name, price); this.category = 'toy'; } var cheese = new Food('feta', 5); var fun = new Toy('robot', 40);
bind
bind 創(chuàng)建一個(gè)新的函數(shù),在 bind() 被調(diào)用時(shí),這個(gè)新函數(shù)的 this 被指定為 bind() 的第一個(gè)參數(shù),而其余參數(shù)將作為新函數(shù)的參數(shù),供調(diào)用時(shí)使用。
特性就是會(huì)有一個(gè)返回值,返回值是一個(gè)擁有第一個(gè)函數(shù)作用域的新的函數(shù)體
函數(shù)名稱.bind(參數(shù)1,參數(shù)2.....)() // 必須調(diào)用一下
參數(shù)1:當(dāng)前函數(shù)的作用域
參數(shù)2:需要傳遞的參數(shù)
var obj = { name:"張三", show:function(val){ console.log(this) //obj 沒有修改前 console.log(this,1) // document 1 修改后 } } obj.show().bind(document,1)()
MDN:ECMAScript 5 引入了 Function.prototype.bind()。調(diào)用 f.bind(someObject) 會(huì)創(chuàng)建一個(gè)與 f 具有相同函數(shù)體和作用域的函數(shù),但是在這個(gè)新函數(shù)中,this 將永久地被綁定到了 bind 的第一個(gè)參數(shù),無(wú)論這個(gè)函數(shù)是如何被調(diào)用的。
apply
apply() 方法調(diào)用一個(gè)具有給定 this 值的函數(shù),以及以一個(gè)數(shù)組(或一個(gè)類數(shù)組對(duì)象)的形式提供的參數(shù)。
函數(shù)名稱.bind(參數(shù)1,[參數(shù)2,a,b,c.....])
參數(shù)1:當(dāng)前函數(shù)的作用域
參數(shù)2:需要傳遞的參數(shù) 數(shù)組
function fn(a,b,c){ console.log(this,a,b,c) } document.onclick = functioin(){ fn.apply(document,[1,2,3]) }
call ,apply ,bind 三者的區(qū)別
不同點(diǎn):
- bind 會(huì)有一個(gè)返回值,返回值是函數(shù)體,因此需要加上 () 才能調(diào)用
- call,apply 是沒有返回值的,當(dāng)改變函數(shù) this 指向的時(shí)候,函數(shù)就會(huì)執(zhí)行,不需要加 () 調(diào)用
- call 傳遞參數(shù)的時(shí)候是一個(gè)一個(gè)傳遞的
- apply 是傳遞一個(gè)數(shù)組或者類數(shù)組對(duì)象的參數(shù)
到此這篇關(guān)于JavaScript this綁定與this指向問題的解析的文章就介紹到這了,更多相關(guān)JavaScript this綁定與this指向內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 一文全面解析JS中的this綁定規(guī)則
- JavaScript中this綁定規(guī)則你理解了嗎
- 細(xì)說(shuō)JavaScript中的this指向與綁定規(guī)則
- JavaScript?中的?this?綁定規(guī)則詳解
- JavaScript中this的綁定你知道幾種?
- 詳解JavaScript中的this硬綁定
- 一文搞懂JavaScript中的this綁定規(guī)則
- JavaScript中?this?的綁定指向規(guī)則
- 詳解JavaScript的this指向和綁定
- JavaScript this綁定過(guò)程深入詳解
- React.js綁定this的5種方法(小結(jié))
- JavaScript調(diào)用模式與this關(guān)鍵字綁定的關(guān)系
- 深入理解JavaScript this綁定規(guī)則
相關(guān)文章
EL表達(dá)式截取字符串的函數(shù)說(shuō)明
這篇文章主要介紹了EL表達(dá)式截取字符串的函數(shù)說(shuō)明,在文章下面給大家介紹了JSTL中自帶的方法列表以及其描述,需要的朋友參考下吧2017-09-09js實(shí)現(xiàn)鼠標(biāo)劃過(guò)給div加透明度的方法
這篇文章主要介紹了js實(shí)現(xiàn)鼠標(biāo)劃過(guò)給div加透明度的方法,涉及javascript動(dòng)態(tài)操作頁(yè)面元素屬性的相關(guān)技巧,該方法可兼容火狐與IE瀏覽器,需要的朋友可以參考下2015-05-05利用JavaScript實(shí)現(xiàn)一個(gè)日期范圍選擇器
日期范圍選擇器是一個(gè)常見的Web應(yīng)用功能,它允許用戶選擇一個(gè)日期范圍,本文我們將使用JavaScript來(lái)實(shí)現(xiàn)這個(gè)功能,感興趣的小伙伴可以了解下2024-01-01JS動(dòng)態(tài)修改iframe內(nèi)嵌網(wǎng)頁(yè)地址的方法
這篇文章主要介紹了JS動(dòng)態(tài)修改iframe內(nèi)嵌網(wǎng)頁(yè)地址的方法,涉及javascript動(dòng)態(tài)修改iframe中src屬性的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04純js實(shí)現(xiàn)的積木(div層)拖動(dòng)功能示例
這篇文章主要介紹了純js實(shí)現(xiàn)的積木(div層)拖動(dòng)功能,結(jié)合實(shí)例形式分析了javascript隨機(jī)生成各種顏色div層及響應(yīng)鼠標(biāo)事件改變?cè)貙傩詫?shí)現(xiàn)拖動(dòng)效果的相關(guān)操作技巧,需要的朋友可以參考下2017-07-07JavaScript欄目列表隱藏/顯示簡(jiǎn)單實(shí)現(xiàn)
隱藏側(cè)邊欄,并將圖片換成右箭頭圖片;顯示側(cè)邊欄,并將圖片換成左箭頭,這樣的效果想必大家都很熟悉吧,接下來(lái)實(shí)現(xiàn)下,感興趣的朋友可以參考下哈2013-04-04javascript中的undefined 與 null 的區(qū)別 補(bǔ)充篇
在Javascript中有兩個(gè)值用來(lái)代表類似空值的概念,undefined和null,這兩個(gè)很容易被混淆,他們表示的是兩個(gè)不同的概念。2010-03-03