摘要:注意因為箭頭函數內部的是指向外層代碼塊的最近的,例中的函數的,所以我們可以通過改變外層代碼塊的的指向從而改變箭頭函數中的指向例中使用了函數的方法。
一、this關鍵字小測試
ES6箭頭函數體中的this指向哪里?
在回答這個問題之前先來揣揣你對this關鍵字的了解程度:
(讓我們回到ES6之前)
題:
var obj = { a: function() { console.log(this); } } var b = obj.a; b();
問:打印出的this的值?
再來幾個選項:
window
obj
document
obj.a
答案是window(可以在控制臺運行一下)
什么!什么情況!發生了什么?
一句話解釋:
一般的,this指向函數運行(調用)時所在的執行環境【《JavaScript高級程序設計》4.2節執行環境及作用域】的(變量)對象(簡單地,this指向函數的調用者)
分析代碼:
var b = obj.a; // ==>相當于 var b = function() { console.log(this); }
函數調用時(b();)其所在的執行環境是全局環境,所以this指向全局變量對象window
二、ES6箭頭函數如果你覺得以上這些都知道了(我會!我會!)那么就繼續吧~~
(來到ES6箭頭函數)
例1【阮一峰《ECMAScript 6 入門》-7.函數的擴展:箭頭函數】
我將阮老師的例子代碼修改了一下:
(普通函數)
function foo() { console.log("id1:", this.id); console.log("this1:", this); setTimeout(function() { console.log("id2:", this.id); console.log("this2:", this); }, 0); } var id = 21; foo(); // Chrome // id1: 21 // this1: window // id2: 21 // this2: window foo.call({id: 42}); // Chrome // id1: 42 // this1: {id: 42} // id2: 21 // this2: window
注意:超時調用(setTimeout回調)的代碼都是在全局作用域環境中執行的,因此(setTimeout回調)函數中this的值在非嚴格模式下指向window對象,在嚴格模式下是undefined
例如
var obj = { console.log(this); setTimeout(function() { console.log(this); }, 0); } obj.a(); // Chrome // {a: f} // window
回到例1
我們使用foo函數的call方法改變了foo函數調用時函數體內this的指向({id: 42}這個對象),但setTimeout回調函數中的this依舊指向window對象(因為在全局環境中運行)。
接下來再將例1改寫一下,將foo函數中的setTimeout回調函數改成箭頭函數的形式:
例2
(箭頭函數)
function foo() { console.log("id1:", this.id); console.log("this1:", this); setTimeout(() => { console.log("id2:", this.id); console.log("this2:", this); }, 0); } var id = 21; foo(); // Chrome // id1: 21 // this1: window // id2: 21 // this2: window foo.call({id: 42}); // Chrome // id1: 42 // this1: {id: 42} // id2: 42 // this2: {id: 42}
foo();的輸出結果沒有變化,但foo.call({id: 42});的輸出結果改變了。
到底發生了什么?
在這里直接給出結論:
箭頭函數根本沒有自己的this,導致內部的this指向了外層代碼的this,這個指向在定義時就已經確定而不會在調用時指向其執行環境的(變量)對象。
注意:因為箭頭函數內部的this是指向外層代碼塊的this(最近的this,例2中的foo函數)的,所以我們可以通過改變外層代碼塊的this的指向從而改變箭頭函數中this的指向(例2中使用了foo函數的call方法)。
重新解釋例2
因為箭頭函數(setTimeout回調)沒有自己的this,導致其內部的this引用了外層代碼塊的this,即foo函數的this,
(要注意:在定義階段(調用函數前),foo函數的this的值并不確定【《JavaScript高級程序設計》第三版5.5.4函數內部屬性】,但箭頭函數的this自定義階段開始就指向foo函數的this了)
又因為使用call方法改變了foo函數運行(調用)時其函數體內this的指向(重新指向對象{id: 42})從而使箭頭函數中this的指向發生變化,最后輸出例2所示結果。
三、例子總結到這里,我想小伙伴們應該是比較清楚了,那么不妨去看看阮一峰老師的《ECMAScript 6 入門》函數的擴展一節箭頭函數部分的一個問題示例:“請問下面的代碼中有幾個this(滑稽)”
加深印象
例3【阮一峰《ECMAScript 6 入門》-19.Class基本語法:this的指向】
class Logger { constructor() { this.printName = (name = "there") => { this.print(`Hello ${name}`); }; } // ... }
箭頭函數中的this指向constructor構造方法內部的this,由于此時constructor中的this尚未獲得值,當通過new命令生成對象實例時,將會自動調用constructor方法,constructor的this才能指向該實例對象,在此過程中,箭頭函數中的this一直引用著constructor中的this,當constructor中this發生變化,箭頭函數的this也會一并發生變化。
若有錯誤,請指出批評!!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93762.html
摘要:在函數方面的擴展比較豐富也很實用,本篇概括了這中的精華知識。所以無法成為構造函數,不能使用操作符。參數將擴展運算符作用于參數,即為參數。聲明式,直接為函數名。通過構造函數生成的,為。函數的屬性,在其描述對象的屬性上,為函數名。 ES6在函數方面的擴展比較豐富也很實用,本篇概括了這中的精華知識。 1 箭頭函數 箭頭函數是ES6中定義函數的新形式。 新形式不僅簡化了定義方式,更為函數本身...
摘要:正是因為它沒有,所以也就不能用作構造函數。不可以當作構造函數,也就是說,不可以使用命令,否則會拋出一個錯誤。不可以使用對象,該對象在函數體內不存在。 箭頭函數 在之前ES5的版本中,我們定義一個函數的形式如下: function a() { // do something…… } 但是在ES6中,則新增了箭頭函數的方式,ES6中允許使用箭頭(=>)來定義函數。 () => { ...
摘要:基礎語法參數參數參數函數聲明參數參數參數表達式單一相當于參數參數參數表達式當只有一個參數時,圓括號是可選的單一參數函數聲明單一參數函數聲明沒有參數的函數應該寫成一對圓括號。 溫馨提示:作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費生命溫馨提示-續:你們要非得看,我也攔不住,但是至少得準備個支持ES6的Chrome瀏覽器吧? 之前在某些大神的代碼中出現一串神秘符號類似于num =>...
摘要:第二種情況是箭頭函數的如果指向普通函數它的繼承于該普通函數。箭頭函數的指向全局,使用會報未聲明的錯誤。 showImg(https://segmentfault.com/img/remote/1460000018610072?w=600&h=400); 箭頭函數是ES6的API,相信很多人都知道,因為其語法上相對于普通函數更簡潔,深受大家的喜愛。就是這種我們日常開發中一直在使用的API...
摘要:對象的指向是可變的,但是在箭頭函數中,它是固定的。同樣的由于箭頭函數沒有自己的所以傳統的顯性綁定無效內部的指向外部在的學習中,的指向問題一直是個難點,特別是在對象方法中使用時,必須更加小心。由此箭頭函數在很大程度上減少了我們的困擾。 什么是箭頭函數 用法 ES6 允許使用箭頭(=>)定義函數 測試 var p1 = document.getElementById(test1)...
閱讀 1538·2021-11-04 16:10
閱讀 2774·2021-09-30 09:48
閱讀 2839·2019-08-29 11:31
閱讀 1578·2019-08-28 18:22
閱讀 3225·2019-08-26 13:44
閱讀 1319·2019-08-26 13:42
閱讀 2845·2019-08-26 10:20
閱讀 754·2019-08-23 17:00