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

