摘要:想方設法糅合過程式與函數式兩種風格,忽略了閉包的基本假設,于是造出天坑。分散在各個閉包中的狀態會成為的溫床。當然,嚴格來說箭頭函數也是一種閉包,因為它是函數和詞法的組合。
編程語言的究極問題:過程式還是函數式?
閉包是函數式編程最先引進的,基本假設就是所有量都是常量。Javascript想方設法糅合過程式與函數式兩種風格,忽略了閉包的基本假設,于是造出天坑。
是什么閉包的定義是“函數和聲明該函數的詞法環境的組合” MDN,換言之,就是帶著環境(上下文、狀態、屬性、局部變量,找一個你能理解的詞)的函數。從ES2015起,最簡單的閉包變成了這樣:
{ let localVar = 1; whatever.onclick = () => localVar++; }
whatever.onclick就是一個閉包,因為它帶著localVar。
從這個角度上來說,所有Javascript函數都是閉包,因為他們都能訪問到window下面的全局變量,如果傳遞給另一個框架的話,用的都是自帶的全局變量環境。
為什么上面的閉包非常糟糕,糟糕就在于它不是純函數,它是有狀態的。分散在各個閉包中的狀態會成為bug的溫床。以foo為例,每次調用都會有副作用,得到的值都不一樣,狀態在哪里又找不著(假設你忘了localVar是啥),給debug造成極大的困難。
現在主流的狀態管理框架Flux/Redux/Vuex的思想全都是集中狀態管理。還把狀態分散到一個一個閉包里面,是過時的。
那我們把狀態保存在哪里?this里。
雖然this也是JS的一個天坑,但是比起閉包來,簡直好太多了。this最偉大的功勛就在于函數和環境的解耦(跟閉包正好相反)。
let bar = function() { this.a++ } let state = { a: 1, bar };
這個時候有同學就要問了,state.bar()還是有副作用的呀,得到的值還是不一樣,好處在哪?好處在于
bar前面是什么?是一個對象state,我們現在能確定bar的副作用在哪里了;
bar本身沒有副作用,只要我們深拷貝state,我們就能歷史回放state.bar()是怎么出bug的。
以上兩點簡直是debug的福音。
怎么辦能減少bug,又實際的寫法:
只有對象保存狀態,不論是字面量,還是new。函數可以讀狀態,寫狀態必須用this.xxx或者用參數把對象傳進來。
為什么說2018(其實2015+就行了)年就可以少用閉包了呢?
因為我們有class關鍵字了,以前創建用得上this的類實在是太麻煩了;
因為我們有箭頭函數了,用閉包保存this的做法也不必要了。
當然,嚴格來說箭頭函數也是一種閉包,因為它是函數和詞法this的組合。但是this能保證只讀,函數并不能用this寫狀態,因此仍然滿足上面說的兩個好處。
所以直接說箭頭函數就是閉包,我天天用,秀面試官一臉就行了,他不懂的話就瀟灑離去,這破地方配不上你 :)
所以,React強推class,Vue用的也是this,都用對象存狀態。既然狀態都被對象存了,自然也就沒閉包什么事了。
我的相關文章Javascript閉包:從理論到實現,[[Scopes]]的每一根毛都看得清清楚楚
以上所有代碼按Mozilla Public License, v. 2.0授權。
以上所有文字內容按CC BY-NC-ND 4.0授權。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/95482.html
摘要:函數是一等公民。其實閉包本身也是函數式編程的一個應用。劣勢不能算是嚴格意義上的函數式語言,很多函數式編程的特性并沒有。 隨著大前端時代的到來,在產品開發過程中,前端所占業務比重越來越大、交互越來越重。傳統的老夫拿起JQuery就是一把梭應付當下重交互頁面已經十分乏力。于是乎有了Angular,React,Vue這些現代框架。 但隨之而來的還有大量的新知識新名詞,如MVC,MVVM,Fl...
摘要:函數是一等公民。其實閉包本身也是函數式編程的一個應用。劣勢不能算是嚴格意義上的函數式語言,很多函數式編程的特性并沒有。 隨著大前端時代的到來,在產品開發過程中,前端所占業務比重越來越大、交互越來越重。傳統的老夫拿起JQuery就是一把梭應付當下重交互頁面已經十分乏力。于是乎有了Angular,React,Vue這些現代框架。 但隨之而來的還有大量的新知識新名詞,如MVC,MVVM,Fl...
摘要:聲明式編程一種編程范式,與命令式編程相對立。常見的聲明式編程語言有數據庫查詢語言,正則表達式邏輯編程函數式編程組態管理系統等。函數式編程,特別是純函數式編程,嘗試最小化狀態帶來的副作用,因此被認為是聲明式的。 編程范式與函數式編程 一、編程范式的分類 常見的編程范式有:函數式編程、程序編程、面向對象編程、指令式編程等。在面向對象編程的世界,程序是一系列相互作用(方法)的對象(Class...
摘要:函數式編程的定義函數是一段可以通過其名稱被調用的代碼。純函數大多數函數式編程的好處來自于編寫純函數,純函數是對給定的輸入返回相同的輸出的函數,并且純函數不應依賴任何外部變量,也不應改變任何外部變量。 一個持續更新的github筆記,鏈接地址:Front-End-Basics,可以watch,也可以star。 此篇文章的地址:JavaScript函數式編程入門經典 正文開始 什么是函...
摘要:從某些方面來講,這章回顧的函數知識并不是針對函數式編程者,非函數式編程者同樣需要了解。什么是函數針對函數式編程,很自然而然的我會想到從函數開始。如果你計劃使用函數式編程,你應該盡可能多地使用函數,而不是程序。指的是一個函數聲明的形參數量。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson - 《You-Dont-Know-JS》作者 關于譯者:...
閱讀 3088·2021-09-22 15:20
閱讀 2608·2019-08-30 15:54
閱讀 1973·2019-08-30 14:06
閱讀 3122·2019-08-30 13:05
閱讀 2467·2019-08-29 18:36
閱讀 578·2019-08-29 15:10
閱讀 533·2019-08-29 11:17
閱讀 830·2019-08-28 18:11