js中this指向混亂問題彙總
阿新 • • 發佈:2022-04-10
彙總下this指向混亂的問題,方便以後多次翻看記憶
this指向混亂主要出現在物件方法中,例如
1 var obj ={ 2 foo: function () { 3 console.log(this); 4 } 5 }; 6 7 obj.foo() // obj
this指向當前物件obj,但如果出現以下幾種情況,那麼this指向會錯誤(即不指向期望的當前物件)
一、物件方法巢狀
物件方法中嵌套了方法,那麼內部方法的this指向會混亂,指向全域性物件,而不是期望的當前物件:
1 var name = '123' 2 var obj = { 3 name:'456',4 getNumber:function(){ 5 function print(){ 6 console.log(this.name) 7 } 8 print() 9 } 10 } 11 12 obj.getNumber() // 123
二、將物件方法當作值使用時
如果將物件方法當作值來使用,那麼該物件方法就脫離了期望的執行環境(即當前物件改變了),js中obj.getNumber和obj的儲存地址不同,當呼叫obj.getNumber()時等於是告訴了js當前物件時obj,但如果如果直接使用obj.foo,則沒有告訴js當前物件,即預設為全域性物件,this不再指向obj
var name = '123' var obj = { name:'456', getNumber:function(){ console.log(this.name) } } const t = obj.getNumber console.log(obj.getNumber()) // 456 console.log(t()) // 123
這個實質上是js初始化物件時的問題,當建立obj物件時,js先建立了{ name:'456', getNumber: ... }後再將這個物件地址賦值給obj
那麼如下程式碼就很好理解了:
1 var a = {2 p: 'Hello', 3 b: { 4 m: function() { 5 console.log(this.p); 6 } 7 } 8 }; 9 10 a.b.m() // undefined
本質上差不多是:
1 var b = { 2 m: function() { 3 console.log(this.p); 4 } 5 }; 6 7 var a = { 8 p: 'Hello', 9 b: b 10 };
那麼就可以理解為什麼this指向混亂了,因為在建立時b.m()不在a的執行環境下,必然拿不到a.p的值
三、forEach和map中this混亂
var o = { v: 'hello', p: [ 'a1', 'a2' ], f: function f() { this.p.forEach(function (item) { console.log(this.v + ' ' + item); }); } } o.f() // undefined a1 // undefined a2
解決辦法
箭頭函式一般可以解決this的指向問題:
var name = '123' var obj = { name:'456', getNumber:function(){ const print = () => { console.log(this.name) } print() } } obj.getNumber() // 456
或者使用call/bind/apply:
var name = '123' var obj = { name:'456', getNumber:function(){ function print() { console.log(this.name) } print.call(this) } } obj.getNumber() // 456
或者可以將this繫結到一個變數中:
比如let that = this,這是一種常見做法
var name = '123' var obj = { name:'456', getNumber:function(){ let that = this function print(){ console.log(that.name) } print() } } obj.getNumber() // 456
對於forEach和map,可以將想繫結的this物件放在最後一個引數中:
var o = { v: 'hello', p: [ 'a1', 'a2' ], f: function f() { this.p.forEach(function (item) { console.log(this.v + ' ' + item); }, this); } } o.f() // hello a1 // hello a2
歸根結底!
1.避免在陣列處理方法中使用this
2.避免多層this
3.避免回撥中的this