摘要:換句話說,箭頭函數構造函數調用沒有意義,而且是模糊的。讓我們看看如果嘗試這樣做會發生什么執行,其中是一個箭頭函數,拋出一個錯誤,不能用作構造函數。當需要動態上下文時,不能使用箭頭函數定義方法,使用構造函數創建對象,在處理事件時從獲取目標。
為了保證的可讀性,本文采用意譯而非直譯。
想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你!
這些年來,ES6 將 JS 的可用性提升到一個新的水平時: 箭頭函數、類等等,這些都很棒。
箭頭函數是最有價值的新功能之一,有很多好文章描述了它的上下文透明性和簡短的語法。
但每個事務都有兩面。通常,新特性會帶來一些混亂,其中之一就是箭頭函數被誤導了。本文將介紹一些場景,在這些場景中,你應該繞過箭頭函數,轉而使用良好的舊函數表達式或較新的簡寫語法。并且要注意縮短代碼,因為這會影響代碼的可讀性。
1.定義對象上的方法在JS中,方法是存儲在對象屬性中的函數。當調用該方法時,this 將指向該方法所屬的對象。
Object literal由于箭頭函數語法簡短,所以使用它來定義方法是很有吸引力的,讓咱們來試一試:
const calculate = { array: [1, 2, 3], sum: () => { console.log(this === window); // => true return this.array.reduce((result, item) => result + item); } }; console.log(this === window); // => true // Throws "TypeError: Cannot read property "reduce" of undefined" calculate.sum();
calculate.sum方法用箭頭函數定義。 但是在調用時,calculate.sum() 會拋出一個TypeError,因為this.array 為undefined。
當調用calculate對象上的方法sum()時,上下文仍然是 window。之所以會發生這種情況,是因為箭頭函數按詞法作用域將上下文綁定到 window 對象。
執行this.array等同于window.array,它是undefined。
解決方法是使用常規函數表達式來定義方法。 this 是在調用時確定的,而不是由封閉的上下文決定的,來看看修復后的版本:
const calculate = { array: [1, 2, 3], sum() { console.log(this === calculate); // => true return this.array.reduce((result, item) => result + item); } }; calculate.sum(); // => 6
因為sum是常規函數,所以在調用 calculate.sum() 時 this 是 calculate 對象。 this.array是數組引用,因此正確計算元素之和:6。
Object prototype同樣的規則也適用于在原型對象上定義方法。使用一個箭頭函數來定義sayCatName方法,this 指向 window
function MyCat(name) { this.catName = name; } MyCat.prototype.sayCatName = () => { console.log(this === window); // => true return this.catName; }; const cat = new MyCat("Mew"); cat.sayCatName(); // => undefined
使用早期的方式定義函數表達式:
function MyCat(name) { this.catName = name; } MyCat.prototype.sayCatName = function() { console.log(this === cat); // => true return this.catName; }; const cat = new MyCat("Mew"); cat.sayCatName(); // => "Mew"
sayCatName常規函數在作為方法調用時將上下文更改為cat對象:cat.sayCatName()。
2. 動態上下文的回調函數this 在JS中是一個強大的特性,它允許根據調用函數的方式更改上下文。通常,上下文是調用發生的目標對象,這使得代碼更加自然,就像這個對象發生了什么。
但是,箭頭函數會在聲明上靜態綁定上下文,并且無法使其動態化,但這種方式有壞也有好,有時候我們需要動態綁定。
在客戶端編程中,將事件偵聽器附加到DOM元素是一項常見的任務。事件觸發處理程序函數,并將this作為目標元素,這里如果使用箭頭函數就不夠靈活。
下面的示例嘗試為這樣的處理程序使用箭頭函數:
const button = document.getElementById("myButton"); button.addEventListener("click", () => { console.log(this === window); // => true this.innerHTML = "Clicked button"; });
在全局上下文中 this 指向 window。 當發生單擊事件時,瀏覽器嘗試使用按鈕上下文調用處理函數,但箭頭函數不會更改其預定義的上下文。this.innerHTML相當于window.innerHTML,沒有任何意義。
必須應用函數表達式,該表達式允許根據目標元素更改 this:
const button = document.getElementById("myButton"); button.addEventListener("click", function() { console.log(this === button); // => true this.innerHTML = "Clicked button"; });
當用戶單擊按鈕時,處理程序函數中的 this 指向 button。因此這個問題。innerHTML = "Clicked button" 正確地修改按鈕文本以反映已單擊狀態。
3.調用構造函數this 在構造調用中是新創建的對象。當執行new MyFunction()時,構造函數MyFunction的上下文是一個新對象:this instanceof MyFunction === true。
注意,箭頭函數不能用作構造函數。 JavaScript通過拋出異常隱式阻止這樣做。
無論如何,this是來自封閉上下文的設置,而不是新創建的對象。換句話說,箭頭函數構造函數調用沒有意義,而且是模糊的。
讓我們看看如果嘗試這樣做會發生什么:
const Message = (text) => { this.text = text; }; // Throws "TypeError: Message is not a constructor" const helloMessage = new Message("Hello World!");
執行new Message("Hello World!"),其中Message是一個箭頭函數,JavaScript拋出一個 TypeError 錯誤,Message不能用作構造函數。
上面的例子可以使用函數表達式來修復,這是創建構造函數的正確方法(包括函數聲明):
const Message = function(text) { this.text = text; }; const helloMessage = new Message("Hello World!");簡寫語法
箭頭函數有一個很好的屬性,它可以省略參數圓括號()、塊大括號{},如果函數主體只有一條語句,則返回。這有助于編寫非常短的函數。
原文作者的大學編程教授給學生一個有趣的任務:編寫 用C語言計算字符串長度的最短函數,這是學習和探索新語言的好方式。
然而,在實際應用程序中,許多開發人員都會閱讀代碼。 最短的語法并不總是適合幫助你的同事即時了解該方法的用途。
在某種程度上,簡寫的函數變得難以閱讀,所以盡量不要過度使用。讓各位們看一個例子
const multiply = (a, b) => b === undefined ? b => a * b : a * b; const double = multiply(2); double(3); // => 6 multiply(2, 3); // => 6
multiply返回兩個數字的乘法結果或與第一個參數綁定的閉包,以便以后的乘法運算。
該函數運行良好,看起來很短。但從一開始就很難理解它是做什么的。
為了使其更具可讀性,可以從箭頭函數恢復可選花括號和return語句,或使用常規函數:
function multiply(a, b) { if (b === undefined) { return function(b) { return a * b; } } return a * b; } const double = multiply(2); double(3); // => 6 multiply(2, 3); // => 6
在簡短和冗長之間找到一個平衡點是很好的,這樣可以使代碼更加直觀。
總結毫無疑問,箭頭函數是一個很好的補充。當正確使用時,它會使前面必須使用.bind()或試圖捕獲上下文的地方變得簡單,它還簡化了代碼。
某些情況下的優點會給其他情況帶來不利。 當需要動態上下文時,不能使用箭頭函數:定義方法,使用構造函數創建對象,在處理事件時從 this 獲取目標。
代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG,花了大量的時間進行log 調試,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
交流干貨系列文章匯總如下,覺得不錯點個Star,歡迎 加群 互相學習。
https://github.com/qq44924588...
我是小智,公眾號「大遷世界」作者,對前端技術保持學習愛好者。我會經常分享自己所學所看的干貨,在進階的路上,共勉!
關注公眾號,后臺回復福利,即可看到福利,你懂的。
附:新文章會提前一天發到公眾號
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106377.html
摘要:我們在需要動態上下文的地方不能使用箭頭函數定義需要動態上下文的函數,構造函數,需要對象作為目標的回調函數以及用箭頭函數難以理解的語句。 從開始接觸es6到在項目中使用已經有一段時間了,es6有很多優秀的新特性,其中最有價值的特性之一就是箭頭函數,他簡潔的語法以及更好理解的this值都非常的吸引我。但是新事物也是有兩面性的,箭頭函數有他的便捷有他的優點,但是他也有缺點,他的優點是代碼簡潔...
摘要:當我們想起箭頭函數時,腦海里可能會浮現棒,酷,簡潔,有趣等形容詞,其實,我們存在一些更充分的理由使我們在聯想起箭頭函數時不得不想到的解決引起的問題箭頭函數不會在函數體內重新定義的值,這使得在回調中的行為更容易預測,并且避免了在回調中潛存的下 當我們想起箭頭函數時,腦海里可能會浮現 棒,酷,簡潔,有趣 等形容詞,其實,我們存在一些 更充分的理由 使我們在聯想起 箭頭函數 時不得不想到的 ...
摘要:顯然,箭頭函數是不能用來做構造函數,實際上會禁止你這么做,如果你這么做了,它就會拋出異常。換句話說,箭頭構造函數的執行并沒有任何意義,并且是有歧義的。 showImg(https://segmentfault.com/img/remote/1460000009180813); 共 2670 字,讀完需 5 分鐘。編譯自 Dmitri Pavlutin 的文章,對原文內容做了精簡和代碼風...
摘要:第二種情況是箭頭函數的如果指向普通函數它的繼承于該普通函數。箭頭函數的指向全局,使用會報未聲明的錯誤。 showImg(https://segmentfault.com/img/remote/1460000018610072?w=600&h=400); 箭頭函數是ES6的API,相信很多人都知道,因為其語法上相對于普通函數更簡潔,深受大家的喜愛。就是這種我們日常開發中一直在使用的API...
摘要:箭頭函數沒有自己的值,箭頭函數中所使用的來自于函數作用域鏈。使用箭頭函數打印對于內層函數,它本身并沒有值,其使用的來自作用域鏈,來自更高層函數的作用域。 《JavaScript 深入淺出》系列: JavaScript 深入淺出第 1 課:箭頭函數中的 this 究竟是什么鬼? JavaScript 深入淺出第 2 課:函數是一等公民是什么意思呢? 普通函數與箭頭函數 普通函數指的是...
閱讀 3332·2021-11-22 14:44
閱讀 2537·2019-08-30 14:10
閱讀 2588·2019-08-30 13:12
閱讀 1217·2019-08-29 18:36
閱讀 1340·2019-08-29 16:16
閱讀 3328·2019-08-26 10:33
閱讀 1761·2019-08-23 18:16
閱讀 379·2019-08-23 18:12