天天看點

javascript筆記之this到底指向哪裡?

本文最最核心的一句話就是:

this

是在函數調用的時候确定的,一定要牢牢記住,其次,在函數執行過程中,

this

一旦被确定,就不可更改了。

var a = 10;
var obj = {
    a: 20
}

function fn(){
	this= obj;  // 這句話試圖修改this,運作後會報錯
	console.log(this.a);
}

fn();
           

this

是什麼

重點:

this

是一個對象,是對象和函數之間達成關聯關系的紐帶,是在函數調用的時候确定。

怎麼确定

this

的指向

因為

this

是在函數調用的時候确定的,是以

this

的指向是很靈活的,是以很多人對

this

的指向總是似懂非懂。那麼這裡可以告訴大家一個套路,也是本文唯一的套路,按照這個套路走,以後

this

的問題再也難不倒你了。

當你不能确定

this

指向哪裡的時候,嘗試把函數的調用轉換為

call/apply

的形式,

call/apply

的第一個參數就是

this

的指向!

call/apply

手動指定

this

call/apply

可以自行手動設定

this

的指向。所有的函數都具有着兩個方法,它們除了參數略有不同,其功能完全一樣。它們的第一個參數都為

this

将要指向的對象。

call/apply

的具體使用這裡就不講了,如果不熟悉

call/apply

的用法 送你傳送門

function fn(param) {
    console.log(this.a,param);
}
var obj = {
    a: "我是this的屬性a"
}

fn.call(obj,"我是參數param"); // 我是this的屬性a  我是參數param
           
  • call/apply

    第一個參數如果傳入的是簡單資料類型,會被自動包裝為對象
    function f(){
      console.log(this)
    }
    f.call(10); 	// Number {10}
    f.call(true);   // Boolean {true}
    f.call("str");  // String {"str"}
               
  • call/apply

    第一個參數如果沒傳,或者傳入的是

    null/undefined

    的時候,

    this

    的指向跟是否在嚴格模式下有關。
    • 非嚴格模式下,

      this

      指向全局對象(浏覽器是

      window

      )。
      function f(){
        console.log(this)
      }
      f.call();    // Window {postMessage: ƒ,...}
      f.call(null);    // Window {postMessage: ƒ,...}
      f.call(undefined); // Window {postMessage: ƒ,...}
                 
    • 嚴格模式下,

      this

      指向

      null/undefined

      "use strict"
      
      function f(){
       console.log(this)
      }
      f.call(); // undefined
      f.call(null);    // null
      f.call(undefined); // undefined
                 

幾個栗子

隻要掌握

call/apply

,結合是否嚴格模式,你就會發現虛無缥缈的

this

已經有迹可循了,下面例子中的函數調用代碼都可以通過轉換的

call

模式代碼直接替換。

  • 純粹的函數調用
    // 非嚴格模式
    var x = 1;
    function test() {
       console.log(this.x);
    }
    
    // 在心裡将test()翻譯為call模式,test.call(),非嚴格模式
    // 是以this===window,是以輸出window.x
    test();  // 1
    
    
    // 嚴格模式
    "use strict"
    var x = 1;
    function test() {
       console.log(this.x);
    }
    // 在心裡将test()翻譯為call模式,test.call(),嚴格模式
    // 是以this===undefined,是以輸出window.x
    test();  // Uncaught TypeError: Cannot read property 'x' of undefined
               
  • 作為對象方法的調用
    function test() {
      console.log(this.x);
    }
    
    var obj = {
    	x:3,
    	m:test
    };
    // 在心裡将test()翻譯為call模式,obj.m.call(obj),這時this===obj,是以輸出obj.x
    obj.m(); // 3
               
    • 作為構造函數調用,

      this

      就指向構造出來的新對象
    function Test() {
     this.x = 3;
    }
    // 在心裡将test()翻譯為call模式
    // var obj = {}; Test.call(obj); 
    // 這時this===obj,是以輸出obj.x
    var obj = new Test();
    obj.x; // 3
               
  • 通過

    call/apply

    改變

    this

    指向,将類數組對象轉換為數組,
    function exam(a, b, c, d, e) {
    
        // 先看看函數的自帶屬性 arguments 什麼是樣子的
        console.log(arguments);
    
        // 使用call/apply将arguments轉換為數組, 傳回結果為數組,arguments自身不會改變
        var arg = [].slice.call(arguments);
    
        console.log(arg);
    }
    
    exam(2, 8, 9, 10, 3);
    // { '0': 2, '1': 8, '2': 9, '3': 10, '4': 3 }
    // [ 2, 8, 9, 10, 3 ]
    // 也常常使用該方法将DOM中的nodelist轉換為數組
    // [].slice.call( document.getElementsByTagName('li') );
               
  • 根據自己的需要靈活修改

    this

    指向
    var foo = {
        name: 'joker',
        showName: function() {
          console.log(this.name);
        }
    }
    var bar = {
        name: 'rose'
    }
    foo.showName.call(bar);
               

總結

我們可以将平時通過括号、通過

.

、通過

new

去使用函數的方式,看做是

call/apply

的文法糖,是簡寫版,想要深入了解函數的調用,就要學好

call

關于

this

的部分已經總結完了,希望這篇文章有助于你準确的了解

this

關鍵字,能夠真正學到東西。

參考

this 的值到底是什麼?一次說清楚

你怎麼還沒搞懂 this?

JS 的 new 到底是幹什麼的?

Javascript 的 this 用法

全方位解讀this

====================================================================================================

作者:星木

歡迎任何形式的轉載,但請務必注明出處。

限于本人水準,如果有不當之處,還請不吝賜教。

繼續閱讀