1. 程式人生 > 其它 >js中this指向混亂問題彙總

js中this指向混亂問題彙總

彙總下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