一篇文章讀懂this關鍵字,不懂,你就聯繫我

前言

與其餘語言相比,函數的 this 關鍵字在 JavaScript中的表現略有不一樣,此外,在嚴格模式和非嚴格模式之間也會有一些差異。本文介紹this在不一樣使用場景的指向問題。git


一、this 並非在編寫的時候綁定的,而是在運行時綁定的。它的上下文取決於函數調用時的各類條件。

二、this 的綁定和函數聲明的位置沒有任何關係,只取決於函數的調用方式。當一個函數被調用時,會建立一個「執行上下文」,這個上下文會包含函數在哪裏被調用(調用棧)、函數的調用方式、傳入的參數等信息。this 就是這個記錄的一個屬性,會在函數執行的過程當中用到。github

原文戳我bash

狀況1、全局性調用,this表明全局對象Global

這是函數的最一般的用法,請看下面這段代碼,不管在函數裏執行,仍是函數外執行,它的運行結果都是2。app

function test () {
        this.x = 2;
        alert(this.x);
    }
    test(); //2
    console.log(this.x) //2
複製代碼

爲了證實this表明全局對象Global,我對代碼做必定的修改,請看下面這段代碼,它的運行結果是1。函數

this.x = 1;
    function test () {
        alert(this.x)
    }
    test(); //1
複製代碼

this表明全局對象,屢次申明表示從新定義,請看下面這段代碼,它的運行結果是2。ui

this.x = 1;
    funtcion test () {
        this.x = 2;
        alert(this.x);
    }
    test(); //2
複製代碼

狀況2、做爲對象方法的調用

函數還能夠做爲某個對象的方法調用,這時this就指這個上級對象。this

this.x = 2;
    function test () {
       alert(this.x); 
    }
    var o = {};
    o.x = 1;
    o.m = test;
    o.m(); //1
複製代碼

狀況3、做爲構造函數調用

this指向構造函數,this再也不是全局變量spa

this.x = 2;
    function test () {
        this.x = 1;
        alert(this.x) //1
    }
    let newTest = new test();
    alert(newTest.x) //1
    alert(x) // 2
複製代碼

狀況4、箭頭函數

1.箭頭函數做爲函數的一種形式,對於this的處理和普通函數有所區別,其沒有本身的this上下文,也就是說經過bind/call/apply函數方法設置this值時無效的,會被忽略。
prototype

2.由於箭頭函數沒有本身的this上下文,那麼當它做爲對象的方法函數運行時,this並不指向這個對象。
code

3.箭頭函數的的函數體中出現的this在運行時綁定到最近的做用域上下文對象。

4.你能夠認爲箭頭函數的this和調用者無關,只和其定義時所在的上下文相關。

function Person() {
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| 正確地指向person 對象
  }, 1000);
}

var p = new Person();
複製代碼
function objWrapper() {
      var a = 10;
      var obj = {
        foo: () => console.log(this.a)
      }
      obj.foo(); 
    }
    objWrapper.call({a:20});//20
    objWrapper();//undefined
複製代碼

狀況5、使用 Function.prototype 中的三個方法 call(), apply(), bind()

這三個函數,均可以改變函數的 this 指向到指定的對象。

上面代碼中, foo() 內部的 this 遵循默認綁定規則,綁定到全局變量中。

而 bar() 在調用的時候,調用了 apply() 函數,把 this 綁定到了一個新的對象中 {a: 2},並且原封不動的接收 foo() 接收的函數。

function foo() {
      console.log(this.a);  // 輸出 1
      bar.apply({a: 2}, arguments);
    }
    function bar(b) {
      console.log(this.a);  // 輸出 2
    }
    var a = 1;
    foo(3);
複製代碼

bind函數的第一個參數若是爲null,this指向全局變量。

this.x = 9; 
    let module = {
      x: 81,
      getX: function() { return this.x; }
    };
    module.getX(); // 返回 81
    let retrieveX = module.getX;
    retrieveX(); // 返回 9, 在這種狀況下,"this"指向全局做用域
    // 建立一個新函數,將"this"綁定到module對象
    // 新手可能會被全局的x變量和module裏的屬性x所迷惑
    let boundGetX = retrieveX.bind(module);
    boundGetX(); // 返回 81
    let reBoundGetX = retrieveX.bind(null,module)
    boundGetX(); // 返回 9

複製代碼
相關文章
相關標籤/搜索