1. 程式人生 > >深入理解ES6箭頭函式的this以及各類this面試題總結

深入理解ES6箭頭函式的this以及各類this面試題總結

ES6中新增了箭頭函式這種語法,箭頭函式以其簡潔性和方便獲取this的特性,俘獲了大批粉絲兒

它也可能是面試中的寵兒, 我們關鍵要搞清楚 箭頭函式和普通函式中的this

一針見血式總結:

普通函式中的this:

1. this總是代表它的直接呼叫者(js的this是執行上下文), 例如 obj.func ,那麼func中的this就是obj

2.在預設情況(非嚴格模式下,未使用 'use strict'),沒找到直接呼叫者,則this指的是 window (約定俗成)

3.在嚴格模式下,沒有直接呼叫者的函式中的this是 undefined

4.使用call,apply,bind(ES5新增)繫結的,this指的是 繫結的物件

箭頭函式中的this

箭頭函式沒有自己的this, 它的this是繼承而來; 預設指向在定義它時所處的物件(宿主物件),而不是執行時的物件, 定義它的時候,可能環境是window; 箭頭函式可以方便地讓我們在 setTimeout ,setInterval中方便的使用this

下面通過一些例子來研究一下 this的一些使用場景[ 使用最新版 chrome測試 ]

要整明白這些, 我們需要首先了解一下作用域鏈:

當在函式中使用一個變數的時候,首先在本函式內部查詢該變數,如果找不到則找其父級函式,

最後直到window,全域性變數預設掛載在window物件下

1.全域性變數預設掛載在window物件下

  1. <script>
  2.  var aa = 2;
  3.  alert(window.aa);
  4.  (function () {
  5.    aa = 3;
  6.  })();
  7.  alert(window.aa);
  8. </script>

我們僅僅聲明瞭一個全域性變數aa,但是打印出window.aa卻和aa保持一致,為什麼呢?

眼見為實, 我們使用console.dir(window) 列印 window物件看看

我們可以看到在window屬性中,看到 aa 屬性了;此外,函式也適用於此情況,全域性函式也會掛在在window物件下

我們常見的window的屬性和方法有: alert, location,document,parseInt,setTimeout,setInterval等,window的屬性預設可以省略window字首!

2.在普通函式中,this指向它的直接呼叫者;如果找不到直接呼叫者,則是window

我們來看一些例子

示例1:

  1. <script>
  2.  function test() {
  3.    console.log(this);
  4.  }
  5.  test();
  6. </script>

結果是: window 

原因: test()是一個全域性函式,也就是說是掛在window物件下的,所以test()等價於 window.test() ,所以此時的this是window

示例2:

  1. <script>
  2.  var obj = {
  3.    say: function () {
  4.      setTimeout(function () {
  5.        console.log(this)
  6.      });
  7.    }
  8.  }
  9.  obj.say();
  10. </script>

結果是: window

匿名函式,定時器中的函式,由於沒有預設的宿主物件,所以預設this指向window

問題: 如果想要在setTimeout/setInterval中使用這個物件的this引用呢?

用一個 變數提前把正確的 this引用儲存 起來, 我們通常使用that = this, 或者 _this = this來儲存我們需要的this指標!

  1. <script>
  2.  var obj = {
  3.    func: function() {},
  4.    say: function () {
  5.      var that = this;   //此時的this就是obj物件
  6.      setTimeout(function () {
  7.        console.log(this)
  8.        that.func()
  9.      });
  10.    }
  11.  }
  12.  obj.say();
  13. </script>

我們也可以使用 func.bind(this) 給回撥函式直接繫結宿主物件, bind繫結宿主物件後依然返回這個函式, 這是更優雅的做法

[javascript] view plain copy
  1. <span style="font-family:'Times New Roman';"><script>  
  2.   var obj = {  
  3.     func: function() {},  
  4.     say: function () {  
  5.        // 此時的this就是obj物件
  6.       setTimeout(function () {  
  7.         console.log(this)  
  8.         this.func()  
  9.       }.bind(this));  
  10.     }  
  11.   }  
  12.   obj.say(); // obj
  13. </script></span>  

示例3(改變自360面試題):
  1.  window.val = 1;
  2.  var obj = {
  3.    val: 2,
  4.    dbl: function () {
  5.      this.val *= 2;
  6.      val *= 2;
  7.      console.log(val);
  8.      console.log(this.val);
  9.    }
  10.  };
  11.  // 說出下面的輸出結果
  12.  obj.dbl();
  13.  var func = obj.dbl;
  14.  func();

結果是:  2   4    8   8

<1> 12行程式碼呼叫

val變數在沒有指定物件字首,預設從函式中找,找不到則從window中找全域性變數

即 val *=2 就是 window.val *= 2

this.val預設指的是 obj.val ;因為 dbl()第一次被obj直接呼叫

<2>14行程式碼呼叫

func() 沒有任何字首,類似於全域性函式,即  window.func呼叫,所以

第二次呼叫的時候, this指的是window, val指的是window.val

第二次的結果受第一次的影響

3.在嚴格模式下的this

  1. <script>
  2.  function test() {
  3.    'use strict';
  4.    console.log(this);
  5.  }
  6.  test();
  7. </script>

結果是: undefined

4.箭頭函式中的 this

  1. <script>
  2.  var obj = {
  3.    say: function () {
  4.      setTimeout(() => {
  5.        console.log(this)
  6.      });
  7.    }
  8.  }
  9.  obj.say(); // obj
  10. </script>

此時的 this繼承自obj, 指的是定義它的物件obj, 而不是 window!

示例(多層巢狀的箭頭函式):

  1. <script>
  2. var obj = {
  3. say: function () {
  4.   var f1 = () => {
  5.     console.log(this); // obj
  6.     setTimeout(() => {
  7.       console.log(this); // obj
  8.     })
  9.   }
  10.   f1();
  11.   }
  12. }
  13. obj.say()
  14. </script>

因為f1定義時所處的函式 中的 this是指的 obj, setTimeout中的箭頭函式this繼承自f1, 所以不管有多層巢狀,都是 obj

示例(複雜情況: 普通函式和箭頭函式混雜巢狀)

  1. <script>
  2. var obj = {
  3. say: function () {
  4.   var f1 = function () {
  5.     console.log(this); // window, f1呼叫時,沒有宿主物件,預設是window
  6.     setTimeout(() => {
  7.       console.log(this); // window
  8.     })
  9.   };
  10.   f1();
  11.   }
  12. }
  13. obj.say()
  14. </script>
結果: 都是 window,因為 箭頭函式在定義的時候它所處的環境相當於是window, 所以在箭頭函式內部的this函式window

示例(嚴格模式下的混雜巢狀)

  1. <script>
  2. var obj = {
  3. say: function () {
  4.   'use strict';
  5.   var f1 = function () {
  6.   console.log(this); // undefined
  7.   setTimeout(() => {
  8.     console.log(this); // undefined
  9.   })
  10.   };
  11.   f1();
  12.  }
  13. }
  14. 相關推薦

    深入理解ES6箭頭函式this以及各類this試題總結

    ES6中新增了箭頭函式這種語法,箭頭函式以其簡潔性和方便獲取this的特性,俘獲了大批粉絲兒它也可能是面試中的寵兒, 我們關鍵要搞清楚 箭頭函式和普通函式中的this一針見血式總結:普通函式中的this:1. this總是代表它的直接呼叫者(js的this是執行上下文), 例

    深入理解ES6箭頭函數中的this

    執行上下文 很多 pre 深入 上下 ber out pri 而不是 簡要介紹:箭頭函數中的this,指向與一般function定義的函數不同,箭頭函數this的定義:箭頭函數中的this是在定義函數的時候綁定,而不是在執行函數的時候綁定。 (1)一般函數this指向在執行

    深入理解Javascript箭頭函式中的this

    今日頭條:https://m.jb51.net/article/105340.htm 新增連結描述 ES6標準新增了一種新的函式:Arrow Function(箭頭函式)。那麼下面這篇文章主要給大家介紹了箭頭函式中this的相關資料,有需要的朋友可以參考借鑑,下面來一起看看吧。 首先我們先看

    ES6箭頭函式修復ES5中this指向問題

    長期以來,ES5中this物件一直的指向一個令人頭痛的問題,在物件方法中使用此,必須非常小心例如: class Animal { constructor(){ this.type = 'animal' } says(say){ setTim

    深入理解ES6函式

    一:關於函式的引數: 可以接受任意數量的引數而無視函式宣告的引數數量是js函式的獨特之處。 1:引數預設值 ES6之前做法: function makeRequest(url,timeout,callback){ timeout=tim

    javascript中的一般函式ES6箭頭函式對比,以及this指向問題的深度理解

    關於this的指向問題,老外有文章寫得非常棒,在看了老外的文章 並結合自己的想法再修改此篇文章 一 、基本概念 本文定義的一般函式 單純 指的是js原生函式(ES5函式) 同時ES5中的作用域只有全域

    es6箭頭函式以及模板字串的拼接

    es6箭頭函式:  //1.具有一個簡單引數的函式 var single=a=>a console.log(single('hello word')); //2.沒有引數的需要在箭頭前加上小括號 var logs=()=>{ console.log('這個是沒有

    js---ES6 箭頭函式this指向

    普通函式的this指向看的是: 1.呼叫者 2.有沒有call/apply改變this指向 3.new改變AO中的this為一個空的物件 4.什麼都沒有,單純呼叫函式,this就是window,在自己的AO中。 箭頭函式的this指向:箭頭函式在定義時執行器上下文的this的指向(不具有塊

    ES6箭頭函式中的this繫結問題

    關於this指向問題的討論一直是學習js不可忽視的重要部分,那些一個又一個圍繞this挖的筆試坑,彷彿永遠也填不完 var obj={ fn:function(){ console.log(this); } } obj.fn();//object  

    深入理解ES6(至第三章-函式

    第一章 塊級作用域繫結 var 宣告初始化變數, 宣告可以提升,但初始化不可以提升。 一、塊級宣告: let const 預設使用,在某種程度上實現程式碼不可變,減少錯誤發生的機率 如果常量是物件,則物件中的值可以修改 不能重複宣告,宣告不會提升 二

    解析ES6箭頭函式中的this

    ES6中新增了箭頭函式這種語法,箭頭函式以其簡潔性和方便獲取this的特性,接下來通過本文給大家分享ES6箭頭函式中的this,寫的十分的全面細緻,具有一定的參考價值,對此有需要的朋友可以參考學習下。如有不足之處,歡迎批評指正。 簡要介紹:箭頭函式中的this,指向與一般fun

    es6 箭頭函式this 指向問題

    箭頭函式體內的this,就是定義時,函式所在的物件,而不是呼叫時所在的物件。 var foo = () => { console.log(this.id); } var id = 1; foo(); // 輸出1 // this 的指向一直是指向 window foo.call(

    ES5,ES6箭頭函式,物件定義中this總結

    最近在學ES6的時候,發現使用箭頭函式的時候的this指向不太清楚,和普通的物件建立做了一些對比,講講自己的理解,有問題希望大家和我一起討論研究 箭頭函式 和 function(){}定義的區別,箭頭函式的 這裡的所有程式碼基於chrome進行測試  這裡有幾個帖子是作為參考的

    ES6 箭頭函式中的 this?(臨時性儲存)

    是否區域性(Lexical)? 包括我在內的許多人,都會這麼描述箭頭函式裡 this 的行為:區域性的 this。什麼意思呢? <body> <div id="demo" onclick="foo()" > 點我</div&

    ES6---箭頭函式與function定義函式有什麼區別?在箭頭函式中,this指向,建構函式,變數提升是如何表現的?

    簡潔 ///function定義函式 function aaa(a,b){ return a+b; } ///箭頭函式定義函式 var aaa=(a,b)=>{return a+b

    深入理解ES6》之解構

    nbsp span 對象 code true 上下文 div 嵌套對象 賦值 結構是一種打破數據解構,將其拆分為更小部分的過程。 對象解構   對象字面量的語法形式是在一個賦值操作符左邊放置一個對象字面量。 let node={ type:"indefi

    深入理解ES6 - var-let-const

    sting fun ret 全局 key 聲明 mas 剛才 syn 知識點 var 聲明變量: 1、存在變量提升,實際上var無論在哪裏聲明,都會被當做當前的作用域頂部聲明變量。 2、可以重復聲明,後聲明的變量會覆蓋前聲明的變量。 let 聲明變量: 1、不存在變量提升。

    JavaScript:學習筆記(5)——箭頭函式=>以及實踐

    JavaScript:學習筆記(5)——箭頭函式=>以及實踐 ES6標準新增了一種新的函式:Arrow Function(箭頭函式)。本文參考的連結如下: MDN箭頭函式:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/

    es6箭頭函式學習

    1.具有一個簡單引數的函式 var single=a=>a console.log(single('hello word')); 2.沒有引數的需要在箭頭前加上小括號 var logs=()=>{ console.log('這個是沒有引數的函式'); } 3.多個引數需

    深入理解ES6》學習筆記二

    5. 解構:使資料訪問更便捷 為何使用解構功能 簡化區域性變數的賦值 為物件和陣列都添加了解構功能 使用var、let或const解構宣告變數, 需提供初始化程式 不能指定為null或undefined