1. 程式人生 > >javascript中this的指向問題

javascript中this的指向問題

this 指的是當前物件,如果在全域性範圍內使用this,則指代當前頁面window;如果在函式中使用this,則this指代什麼是根據當前函式是在什麼物件上呼叫。我們可以使用call和apply改變函式中this的具體指向。另外,在建構函式或者建構函式原型物件中this指向建構函式的例項。

1.全域性作用域或者普通函式中this指向全域性物件window

console.log(this === window)  // true
console.log(window.alert === this.alert)  // true
console.log(this.parseInt("051",10))  // 51

注意:全域性作用域中函式中的this,在嚴格模式下,這種函式中的this等於undefined

  "use strict";
    
    console.log("嚴格模式");
    console.log('在全域性作用域中函式中的this');
    function f1(){
      console.log(this);
    }
    
    function f2(){
      function f3(){
        console.log(this);
      }
      f3();
    }
    f1();//undefined
    f2();//undefined

2.函式中的this是在執行時候決定的,而不是函式定義時。

    function boy(){
            console.log(this.man);
    }
    // 定義一個全域性變數,等同於window.man = "Tom";
    var man= "Tom";
    // 此時函式中的this指向window;
    boy();  //   "Tom"
    
    var  b = {
          man : "Jim",
          boy: boy
    };
    // 此時函式中的this指向物件 b
    b.boy();  // "Jim"

全域性函式apply和call可以用來改變this的指向,如下:

function boy(){
            console.log(this.man);
    }
    // 定義一個全域性變數,等同於window.man= "Tom";
    var boy= "Tom";

    var  b = {
          man: "Jone"
    };
    
    boy.apply(window);  // "Tom";
    boy.call(b);  // "Jone";

apply的引數需要放在一個數組裡面,而call不需要,舉例:

function boy(){
         if(this === window){
             console.log("this is window");
        }   
    };
    // 函式boy也是物件,可以為物件定義屬性,然後屬性為函式
    boy.boo = function(){
        if(this === boy){
             console.log("this is boy");       
        }else if(this === window){
                console.log("this is window");
            }
    };
    
    // 等價於 window.boy();
    boy();  // "this is window";
    // 可以看到函式中this的指向呼叫函式的物件
    boy.boo();  // "this is boy";
    // 可以使用call改變函式中this指向
    boy.boo.call(window); // "this is window";

3.物件中的巢狀函式的this指向不是當前物件,而是window:

var name = "window.name";
      var obj = {
          name : "obj.name",
          getName:function(){
              console.log(this.name);
              return function(){
                  console.log(this.name);
              } 
          }
      }
      obj.getName()();  // "obj.name"  "window.name"

要怎樣解決上述問題呢?主要有三種解決辦法,如下:

(1).使用函式的bind方法,綁定當前this;

var name = "window.name";
      var obj = {
          name : "obj.name",
          getName:function(){
              console.log(this.name);
              return function(){
                  console.log(this.name);
              }.bind(this);
          }
      };
      obj.getName()();  //  "obj.name"  "obj.name"

(2).使用變數將上面的this接收一下,然後下面不使用this,使用那個變數;

var name = "window.name";
      var that = null;
      var obj = {
          name : "obj.name",
          getName:function(){
              that = this;
              console.log(this.name);
              return function(){
                  console.log(that.name);
              }
          }
      }
      obj.getName()();  //  "obj.name"    "obj.name"

(3).使用ES6的箭頭函式,可以完美避免此問題;

var name = "window.name";
      var obj = {
          name : "obj.name",
          getName:function(){
              console.log(this.name);
              return () => {
                  console.log(this.name);
              }
          }
      }
      obj.getName()();    //  "obj.name"    "obj.name"

4.函式作為建構函式,用new關鍵字呼叫時:this指向新new出的物件

//不使用new指向window
function Man(name) {
    console.log(this) 
    this.name = name;
}
Man('nonew');// window
//使用new
function Man(name) {
      this.name = name
      console.log(this) 
      self = this
  }
  var people = new Man('new') //people
  console.log(self === people) //true
//這裡new改變了this指向,將this由window指向Man的例項物件people
5. 事件處理函式中的this;在嚴格模式下,在事件處理函式中,this指向觸發事件的目標物件。
z注意:內聯事件處理
當代碼在元素上進行呼叫處理,this指向的是這個DOM元素.
<button onclick="alert(this.tagName.toLowerCase());">
Show this
</button>

上面顯示的是這個按鈕. 記住只有這種方式,返回的是這個元素.
<button onclick="alert((function(){return this}()));">
Show inner this
</button>

在這個例子中,內部函式this沒有被設定,因此它返回的全域性物件window.