探討奇技淫巧

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

探討奇技淫巧

起源

在工程實踐中,我們常常會遇到一些奇技淫巧。所謂奇技淫巧,就是官方在設計或者實踐中并未想象出的代碼風格或者使用場景。其實也就是類似于 react 的 hoc,本來源自于社區,但是該方案卻成為了官方肯定的方案。那么究竟應不應在平時學習呢?究竟應不應該在工程中使用呢,或者使用怎么樣的奇技淫巧。

兩年前。我還沒有畢業,在大學的最后一個學期中選擇了進入前端,同時,被吸引到前端陣營中一個不得不說的原因就是 js 的奇技淫巧,同時個人是一個比較獵奇的人,所以就學了很多關于 js 的奇技淫巧。

現在這些奇技淫巧要么變成了這門語言不可或缺的一部分,要么隨著時間的推移而消失,還有一些在不知不覺中卻忘記了,既然這次的文章是介紹這方面的知識,也就多介紹一下之前學習的一些例子。

~ 運算符 + indexOf

在 es6 includes 尚未推行之前,我們判斷判斷字符串或者數組包含只能使用 indexOf 這個方法,但是 indexOf 返回的確實元素的索引,如果不存在則返回 -1。 因為在之前寫 c 語言的時候,我們往往使用 0 代表成功,1 2 3代表著不同的錯誤。因為0是獨一無二的。在類c的語言中是具有 truthy falsy 這個概念。并不指代bool的 true 與 false。

下表代表了js 的 truthy 以及 falsy。

變量類型falsytruthy
布爾falsetrue
字符串" "非空字符串
數值0 NaN任何不為falsy的數值
null
undefined
對象(數組), {} 以及 []

對于數值而言,我們知道 0 對于數值是唯一的,而 -1不是。那么我們可以通過 ~ 運算符來把-1 變為 0.

~-1
// 0
~1
//-2

解釋下
對每一個比特位執行非(NOT)操作。NOT a 結果為 a 的反轉(即反碼)。

9 (base 10) = 00000000000000000000000000001001 (base 2)   ~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base 10)

因為在計算機中第一位代表著 符號位置。

同時簡單理解。對任一數值 x 進行按位非操作的結果為 -(x + 1)。 也就是說通過 ~ 可以把 -1(且僅僅只是 -1) 變為 falsy。

var str = 'study pwa';
var searchFor = 'a';// 這是 if (str.indexOf('a') > -1) 或者 if ( -1 * str.indexOf('a') <= 0) 條件判斷的另一種方法
if (~str.indexOf(searchFor)) {// searchFor 包含在字符串 str 中
} else {// searchFor 不包含在字符串 str 中
}

惰性函數

沒學習惰性函數時候,如果創建 xhr,每次都需要判斷。

function createXHR(){var xmlhttp;try{//firfox,opear,safarixmlHttp=new XMLHttpRequest();} catch(e) {try{xmlHttp=new ActiveXobject('Msxm12.XMLHTTP');} catch(e) {try{xmlHttp=new ActiveXobject("Microsoft.XMLHTTP")} catch(e) {alert("您的瀏覽器不支持AJAX")return false;}}}return xmlHttp;
}

在學習完了惰性函數之后

function createXHR(){// 定義xhr,var xhr = null;if (typeof XMLHttpRequest!='undefined') {xhr=new XMLHttpRequest();createXHR=function(){return new XMLHttpRequest();  //直接返回一個懶函數}} else {try{xhr=new ActiveXObject("Msxml2.XMLHTTP");createXHR=function(){return new ActiveXObject("Msxml2.XMLHTTP");}} catch(e) {try{xhr =new ActiveXObject("Microsoft.XMLHTTP");createXHR=function(){return new ActiveXObject("Microsoft.XMLHTTP");}} catch(e) {createXHR=function(){return null}}        }}// 第一次調用也需要 返回 xhr 對象,所以需要返回 xhrreturn xhr;
}

如果代碼被使用于兩次調用以上則會有一定的性能優化。第一次調用時候 把 xhr 賦值并返回,且在進入層層 if 判斷中把 createXHR 這個函數賦值為其他函數。

 // 如果瀏覽器中有 XMLHttpRequest 對象在第二次調用時候createXHR=function(){return XMLHttpRequest();  //直接返回一個懶函數}

該方案可以在不需要第二個變量的情況下直接對函數調用進行優化。同時對于調用方也是透明的,不需要修改任何代碼。

擴展運算符號的另類用法

在最近的學習中,我看到了一篇關于 ... (擴展運算符)的另類用法,The shortest way to conditional insert properties into an object literal, 這篇文章介紹了如何最簡化的寫出條件性插入對象屬性。

在沒有看過這篇文章時會寫出如下代碼:

// 獲得手機號
const phone = this.state.phoneconst person = {name: 'gogo',age: 11
}// 如果手機號不為空,則添加到person中
if (phone) {person.phone = phone
}

但是,看完該文章之后可以寫出這樣的代碼

// 獲得手機號
const phone = this.state.phoneconst person = {name: 'gogo',age: 11,...phone && {phone}
}

上面的代碼與該代碼功能相同,但是代碼量卻減少很多。

要理解上述代碼的運行原理,首先先介紹一下 ... 運算符, 對象的擴展運算符(...)用于取出參數對象的所有可遍歷屬性,拷貝到當前對象之中。

let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }// 如果是 空對象,沒有任何效果
{...{}, a: 1}
// { a: 1 }// 如果擴展運算符后面不是對象,則會自動將其轉為對象。但是如果對象沒有屬性,就會返回空對象
// {...1} 會變為 {...Object(1)} 但是因為沒有屬性
{...1} 
// {}// 同理得到
{...undefined} {...null} {...true}
// 都會變為 {}

可以參考 阮一峰的 es6入門的對象的擴展運算符

原理是因為代碼可以如下理解:

const obj = {...(phone && {phone})
}// 如果 phone 有數據,&& 執行則會變為
const obj = {...{phone}
}
// 而對象擴展運算符 執行就會變為
const obj = {phone
}但是 如果 phone 為空字符串或者其他 falsy 數據,則代碼會直接短路
const obj = {...false...null...0...undefined
}
則不會添加任何屬性進入對象

討論與思考

關于 ~ 操作符 + indexOf 其實加深了對位運算與比特位的理解。但是在es6之后我們完全可以使用 includes。完全可以不再使用~indexOf。

對于惰性函數,在typescript中,該代碼是不可以使用的。當然,我們可以通過函數變量以及增加代碼實現上述功能。

function createXHR(){}
// 修改為
let createXHR = function() {// ...
}

這里也可以看出 ts 不認可函數聲明的函數名是一個變量。

對于擴展運算符的特殊用法。關于 typescript 使用,上述代碼是可以在ts中使用的,不過不可以使用 &&,要使用 三元運算符

{...phone ? {phone} : {}
}

但是不建議在ts中使用,因為該代碼不會被代碼ts檢測到。

const phone = '123'// 定義接口
interface Person {name: string;
}// 不會爆出 error
const person: Person = {name: 'ccc',...phone ? {phone} : {}
}

該代碼是與 ts 嚴重相悖的,ts首要就是類型定義,而使用該代碼逃出了 ts 的類型定義,這個對于語言上以及工程維護上是無法接受的。 同樣的代碼,我認為 js 是可以接受的(但是未必要在工程中使用),但是 ts 確實無法接受的,這也是不同的語言之間的差異性。

在關于這片文章的評論中,最大的論點在于 為什么要使用最簡的代碼,最好的代碼應該是不言自明的。

而作者也相對而言探討了自己的一些看法,應該學習一些自己不理解的東西。同時如果一個東西能夠解釋來龍去脈,完全可以從原理性解釋,那么值得學習與使用。同時我個人其實是和作者持著相同意見的。

總結

  • js 是一門靈活的語言(手動滑稽)。
  • 應該多學習一些奇技淫巧,因為很多奇技淫巧往往代表一些混合的知識,往往會有一些新奇的思考與體驗(怎么我想不出來?)同時,在別人使用了奇技淫巧時候我可以迅速理解。
  • 在項目中是否使用此類代碼要取決團隊類型,以及項目體系,并非個人喜惡。

鼓勵一下

如果你覺得這篇文章不錯,希望可以給與我一些鼓勵,在我的 github 博客下幫忙 star 一下。 博客地址

參考資料

The shortest way to conditional insert properties into an object literal

對象的擴展運算符

轉載于:https://my.oschina.net/wsafight/blog/3058605

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/536418.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536418.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536418.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

悼念512汶川大地震遇難同胞——選拔志愿者【博奕】

悼念512汶川大地震遇難同胞——選拔志愿者 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 11716 Accepted Submission(s): 7537 Problem Description 對于四川同胞遭受的災難&#xff0c;全國人民紛紛伸出援…

mall整合SpringBoot+MyBatis搭建基本骨架

本文主要講解mall整合SpringBootMyBatis搭建基本骨架&#xff0c;以商品品牌為例實現基本的CRUD操作及通過PageHelper實現分頁查詢。 mysql數據庫環境搭建 下載并安裝mysql5.7版本&#xff0c;下載地址&#xff1a;dev.mysql.com/downloads/i…設置數據庫帳號密碼&#xff1a;r…

Web框架之Django_01初識(三大主流web框架、Django安裝、Django項目創建方式及其相關配置、Django基礎三件套:HttpResponse、render、redirect)...

摘要&#xff1a; Web框架概述 Django簡介 Django項目創建 Django基礎必備三件套(HttpResponse、render、redirect) 一、Web框架概述&#xff1a; Python三大主流Web框架&#xff1a; Django&#xff1a;大而全&#xff0c;自帶了很多功能模塊&#xff0c;類似于航空母艦&am…

Bone Collector【01背包】

F - Bone Collector HDU - 2602 Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave … The bone collector had a big bag wit…

Gamma階段第八次scrum meeting

每日任務內容 隊員昨日完成任務明日要完成的任務張圓寧#91 用戶體驗與優化https://github.com/rRetr0Git/rateMyCourse/issues/91&#xff08;持續完成&#xff09;#91 用戶體驗與優化https://github.com/rRetr0Git/rateMyCourse/issues/91牛宇航#86 重置密碼的后端邏輯https:/…

【動態規劃】多重背包

問題 Q: 【動態規劃】多重背包 時間限制: 1 Sec 內存限制: 64 MB 提交: 112 解決: 49 [提交] [狀態] [討論版] [命題人:admin] 題目描述 張琪曼&#xff1a;“魔法石礦里每種魔法石的數量看起來是足夠多&#xff0c;但其實每種魔法石的數量是有限的。” 李旭琳&#xff1a;…

【動態規劃】完全背包問題

問題 O: 【動態規劃】完全背包問題 時間限制: 1 Sec 內存限制: 64 MB 提交: 151 解決: 71 [提交] [狀態] [討論版] [命題人:admin] 題目描述 話說張琪曼和李旭琳又發現了一處魔法石礦&#xff08;運氣怎么這么好&#xff1f;各種嫉妒羨慕恨啊&#xff09;&#xff0c;她們有…

springboot超級詳細的日志配置(基于logback)

前言 java web 下有好幾種日志框架&#xff0c;比如&#xff1a;logback&#xff0c;log4j&#xff0c;log4j2&#xff08;slj4f 并不是一種日志框架&#xff0c;它相當于定義了規范&#xff0c;實現了這個規范的日志框架就能夠用 slj4f 調用&#xff09;。其中性能最高的應該使…

【動態規劃】簡單背包問題II

問題 J: 【動態規劃】簡單背包問題II 時間限制: 1 Sec 內存限制: 64 MB 提交: 127 解決: 76 [提交] [狀態] [討論版] [命題人:admin] 題目描述 張琪曼&#xff1a;“為什么背包一定要完全裝滿呢&#xff1f;盡可能多裝不就行了嗎&#xff1f;” 李旭琳&#xff1a;“你說得…

Vue組件通信

前言 Vue組件之間的通信 其實是一種非常常見的場景 不管是業務邏輯還是前段面試中都是非常頻繁出現的 這篇文章將會逐一講解各個傳值的方式 不過在此之前 先來總結一下各個傳值方式吧 1.父組件向子組件傳值 > props2.子組件向父組件傳值 > $emit3.平級組件傳值 > 總線…

【動態規劃】0/1背包問題

問題 H: 【動態規劃】0/1背包問題 時間限制: 1 Sec 內存限制: 64 MB 提交: 152 解決: 95 [提交] [狀態] [討論版] [命題人:admin] 題目描述 張琪曼和李旭琳有一個最多能用m公斤的背包&#xff0c;有n塊魔法石&#xff0c;它們的重量分別是W1&#xff0c;W2&#xff0c;…&a…

貓哥教你寫爬蟲 005--數據類型轉換-小作業

小作業 程序員的一人飲酒醉 請運用所給變量&#xff0c;使用**str()**函數打印兩句話。 第一句話&#xff1a;1人我編程累, 碎掉的節操滿地堆 第二句話&#xff1a;2眼是bug相隨, 我只求今日能早歸 number1 1 number2 2 unit1 人 unit2 眼 line1 我編程累 line2 是bug相…

索引失效

轉載于:https://blog.51cto.com/11009785/2406488

棋盤問題【深搜】

棋盤問題 POJ - 1321 在一個給定形狀的棋盤&#xff08;形狀可能是不規則的&#xff09;上面擺放棋子&#xff0c;棋子沒有區別。要求擺放時任意的兩個棋子不能放在棋盤中的同一行或者同一列&#xff0c;請編程求解對于給定形狀和大小的棋盤&#xff0c;擺放k個棋子的所有可行…

python isinstance()

isinstanceisinstance(object, classinfo) 判斷實例是否是這個類或者object是變量 classinfo 是類型(tuple,dict,int,float) 判斷變量是否是這個類型 舉例&#xff1a; class objA: pass A objA() B a,v C a string print isinstance(A, objA) #注意該用法 print isinst…

P1303 A*B Problem 高精度乘法

復習了一下高精乘 #include<bits/stdc.h> using namespace std; const int maxn1e67; char a1[maxn],b1[maxn]; int a[maxn],b[maxn],c[maxn*10],lena,lenb,lenc,x; int main() {scanf("%s",a1);scanf("%s",b1);lenastrlen(a1);lenbstrlen(b1);for(i…

Catch That Cow【廣搜】

Catch That Cow POJ - 3278 Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number l…

Go2Shell 已無法使用

在更新 Mac 系統時提醒了這個, 像我一樣對 Go2Shell 中毒的人來說, 這是無法忍受的。貌似 Go2Shell 沒有升級&#xff0c;沒有辦法&#xff0c;就直接找來了一個替代品。cd to, 下載入口如下&#xff1a;目前感覺良好。 轉載于:https://juejin.im/post/5cfe82e15188252b1b0366e…

Fliptile【搜索】

Fliptile POJ - 3279 Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a brainy activity for cows in which they manipulate an M N grid (1 ≤ M ≤ 15; 1 ≤ N ≤ 15) of square tiles, each of which…

JS異步開發總結

1 前言 眾所周知&#xff0c;JS語言是單線程的。在實際開發過程中都會面臨一個問題&#xff0c;就是同步操作會阻塞整個頁面乃至整個瀏覽器的運行&#xff0c;只有在同步操作完成之后才能繼續進行其他處理&#xff0c;這種同步等待的用戶體驗極差。所以JS中引入了異步編程&…